﻿//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
// 프로그램 명		: cFunction.cs
// 프로그램 기능	: 공용 함수 클래스 라이브러리
// 클래스 기능		: 공통으로 사용되는 함수 정의
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 개발자			: 김승현, 조범준
// 개발일			: 2014-06-17
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// F/W 버전		    : Dot NET Compack Framework 4.0 Service Pack 1 Patch
// 라이센스			: Copyright ⓒ 2014-2014 All rights reserved.
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 명명규칙			: 클래스(class) 명				- "c" + 클래스명
//					  전역(private) 상수			- "MC_" + 상수명
//					  공용(public)  상수			- "PC_" + 상수명
//					  전역(private) 변수/객체/핸들/구조체/컬렉션/델리게이트
//													- "mv_" + 타입/obj_/hwnd_/stru_/coll_/del_ + 명
//					  공용(public)  변수/객체/핸들/구조체/컬렉션/델리게이트/이벤트
//													- "pv_" + 타입/obj_/hwnd_/stru_/coll_/del_/evnt_ + 명
//					  공용(public)  속성(Property)	- "pp_" + 타입 + 속성명
//					  전역(private) 함수/API		- "mf_" + 함수명/API 함수명
//					  공용(public)  함수/API		- "pf_" + 함수명/API 함수명
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
// 개발자는 개발/수정시 위의 내용을 반드시 작성하며 내용이 일치하지 않을때에는 모든 사항을 개발자가 책임 진다.
//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Collections.Specialized;
using System.Drawing;
using System.Collections;
using System.Reflection;
using System.Net;
//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
namespace ComCls
{
	///▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
	/// <summary>cFunction 클래스</summary>
	///▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
	public class cFunction
	{
		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [생성자/소멸자]
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>생성자</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		public cFunction(Form frmOwner)
		{
			this.mv_oFuncOwner = frmOwner;

			mf_Init(this);
		}
		public cFunction()
		{
			mf_Init(this);
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>소멸자</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		~cFunction()
		{
			mf_UnInit(this);
		}
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [전역(private) 상수/나열형 - 클래스 내부만 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 상수명 첫 문자는 "MC_" 로 시작
		//         - 전체를 영문 대문자로 하고 상수명이 긴 경우 '_'로 구분해서 명명
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		///<summary>전역(private) 상수 선언 예</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		private const string MC_HELLO = "Hello...";
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [공용(public) 상수/나열형 - 클래스 외부로 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 상수명 첫 문자는 "PC_" 로 시작
		//         - 전체를 영문 대문자로 하고 상수명이 긴 경우 '_'로 구분해서 명명
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		///<summary>공용(public) 상수 선언 예</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		public const string PC_HELLO = "Hello...";
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [전역(private) 변수/객체/핸들/구조체/컬렉션/델리게이트 - 클래스 내부만 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 첫 문자를 "mv_타입"/"mv_obj"/"mv_hwnd"/"mv_struc"/"mv_coll"/"mv_del" 로 시작
		//         - 영문 대소문자로 시작하고 변수명이 긴 경우 대소문자 구분해서 명명('_' 사용가능!)
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>전역(private) 변수 선언 예</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		private string mv_sHello = null;
		//---------------------------------------------------------------------------------------------------
		//객체 변수 관련
		//---------------------------------------------------------------------------------------------------
		private static Hashtable mv_hashBomApplication = new Hashtable();				//BOM 어플리케이션 인스턴스 핸들 버퍼(스태틱)
		private Form mv_oFuncOwner = null;												//함수를 호출한 소유자
		private WinHttp.WinHttpRequest mv_oWinHTTP = new WinHttp.WinHttpRequest();		//WinHTTP 프로토콜 객체
		private Color mv_TreeNodeDefaultBackColor;										//트리노드를 복사 또는 이동시 소스의 기본 바탕색 저장
		private Color mv_TreeNodeSelectBackColor = Color.LightSteelBlue;				//트리노드를 복사 또는 이동시 소스의 선택 바탕색 저장
		//---------------------------------------------------------------------------------------------------
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [공용(public) 변수/객체/핸들/구조체/컬렉션/델리게이트/이벤트 - 클래스 외부로 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 첫 문자를 "pv_타입"/"pv_obj"/"pv_hwnd"/"pv_struc"/"pv_coll"/"pv_del"/"pv_event" 로 시작
		//         - 영문 대소문자로 시작하고 변수명이 긴 경우 대소문자 구분해서 명명('_' 사용가능!)
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>공용(public) 변수 선언 예</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pv_sHello = null;
		//---------------------------------------------------------------------------------------------------
		//디버그 에서 시간 계산 관련
		//---------------------------------------------------------------------------------------------------
		public DateTime pv_Debug_dtStartSqlExec;										//Sql 실행 시작 시간
		public DateTime pv_Debug_dtStartOutputDataSet;									//DataSet 출력 시작 시간
		public static TimeSpan pv_Debug_tsIntervalSecSqlExec;							//Sql 실행 시간 계산용
		public static TimeSpan pv_Debug_tsIntervalSecOutputDataSet;						//DataSet 출력 시간 계산용
		//---------------------------------------------------------------------------------------------------
		//메뉴 관련
		//---------------------------------------------------------------------------------------------------
		public int pv_Menu_nInitNumber = 0;												//새로 등록하기 위한 메뉴의 초기 번호
		public bool pv_Menu_bNumberInitOK = false;										//pv_nMenuInitNumber 값 결정 여부
		public static ToolStripMenuItem pv_Menu_menuParentForBomClients = null;			//실행된 BOM Client를 메뉴로 등록할 부모 메뉴 핸들(스태틱)
		public static ToolStrip pv_Menu_toolbarMain = null;								//메인 화면에 있는 툴바 핸들(스태틱)
		public delegate void pv_Menu_delMenuBomApp(string sBomAppTitle);				//메뉴 클릭 시 실행할 BOM 어플리케이션 인스턴스 원형
		//---------------------------------------------------------------------------------------------------
		//데이터그리드 뷰 관련
		//---------------------------------------------------------------------------------------------------
		public int pv_DataGridView_nJobModeColIndex = -1;								//DataGridView에 CRUD 정보를 갖고있는 컬럼Index
		public bool pv_DataGridView_bRowHeaderAllImageUseOK = true;						//DataGridView에 행 이미지 전체 사용 여부
		public bool pv_DataGridView_bRowHeaderReadImageUseOK = true;					//DataGridView에 행 기본 이미지(읽기) 사용 여부
		//---------------------------------------------------------------------------------------------------
		//트리뷰 관련(함수 포인터(델리게이트))
		//---------------------------------------------------------------------------------------------------
		//public delegate bool pv_delTreeView_BeforeExpand(TreeView oTreeView, TreeViewCancelEventArgs e, TreeNode oTreeNode, bool bTreeNodeExpandAlwaysDbReadOK);	//TreeView_BeforeExpand 이벤트 핸들러에서 실행할 함수 포인터 원형
		public delegate bool pv_TreeView_delBeforeExpand(TreeView oTreeView, TreeViewCancelEventArgs e, TreeNode oTreeNode, bool bTreeNodeExpandAlwaysDbReadOK);	//TreeView_BeforeExpand 이벤트 핸들러에서 실행할 함수 포인터 원형
		public delegate bool pv_TreeView_delDragDrop(TreeView oTreeView, DragEventArgs e, TreeNode oTreeNodeDragSource, TreeNode oTreeNodeDragTarget);				//TreeView_DragDrop 이벤트 핸들러에서 실행할 함수 포인터 원형
		public delegate bool pv_TreeView_delContextMenuClick(TreeView oTreeView, ContextMenu oContextMenu, MenuItem oMenuItem, int nSelectedIndex);					//TreeView_ContextMenuClick 이벤트 핸들러에서 실행할 함수 포인터 원형
		public pv_TreeView_delBeforeExpand pv_TreeView_delBeforeExpand_FunctionName = null;			//트리뷰에서 노드가 확장될때 실행할 함수 포인터
		public pv_TreeView_delDragDrop pv_TreeView_delDragDrop_FunctionName = null;					//트리뷰에서 노드 드롭될때 실행할 함수 포인터
		public pv_TreeView_delContextMenuClick pv_TreeView_delContextMenuClick_FunctionName = null;	//트리뷰 컨텍스트 메뉴에서 클릭할 때 실행할 함수 포인터

		public int pv_TreeView_nTreeNodeDragDropLevel = -1;																			//트리뷰 노드를 드래그 드롭할 때 가능한 레벨
		public bool pv_TreeView_bTreeNodeExpandAlwaysDbReadOK = ComCls.cConst.PC_TREEVIEW_NODEEXPAND_DBREAD_ALWAYS;					//트리뷰 노드가 확장될 때 항상 데이터베이스에서 하위노드를 읽는지 여부
		public ComCls.cConst.PE_TREEVIEW_DATASTATUS pv_TreeView_eTreeViewStatus = ComCls.cConst.PE_TREEVIEW_DATASTATUS.START;		//TreeView 노드 구성 상태
		public ComCls.cConst.PE_TREEVIEW_DATASTATUS pv_TreeView_eTreeListViewStatus = ComCls.cConst.PE_TREEVIEW_DATASTATUS.START;	//TreeListView 노드 구성 상태

		public ContextMenu pv_TreeView_cmTreeView = null;											//트리뷰 컨텍스트 메뉴 객체 핸들
		//---------------------------------------------------------------------------------------------------
		//트리 리스트 뷰 관련
		//---------------------------------------------------------------------------------------------------
		public MouseEventArgs pv_pTreeListItemMouse;												//트리 리스트 뷰 에서 아이템을 찾기위한 마우스 위치값
		//---------------------------------------------------------------------------------------------------
		//파일 업/다운로드 관련(델리게이트 및 이벤트)
		//---------------------------------------------------------------------------------------------------
		public delegate void UpDownloadFileCompleted(object sender, cConst.pv_strucFileUpDownloadInfo strucFileUpDownloadInfo);
		public event UpDownloadFileCompleted OnUpDownloadFileCompleted;								//파일 업/다운로드 이벤트
		//---------------------------------------------------------------------------------------------------
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [공용(public) 속성(Property:읽기 쓰기 선택적 가능) - 클래스 외부로 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 첫 문자를 "pp_타입" 로 시작
		//         - 영문 대소문자로 시작하고 속성명이 긴 경우 대소문자 구분해서 명명('_' 사용가능!)
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>공용(public) 속성(Property) 선언 예</summary>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pp_bHello
		{
			get { return mv_sHello; }
			set { mv_sHello = value; }
		}
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [전역(private) 함수/API - 클래스 내부만 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 첫 문자를 "mf_" + 함수명 또는 API 함수명 으로 시작
		//         - 영문 대소문자로 시작하고 함수명이 긴 경우 대소문자 구분해서 명명('_' 사용가능!)
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>전역(private) 함수 선언 예</summary>
		/// <param name="sStr">전역(private) 함수 인자 선언 예</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private string mf_Hello(string sStr)
		{
			try
			{
				sStr = "Hello...";
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sStr;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>클래스 초기화</summary>
		/// <param name="objClass">클래스 객체 인스턴스</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void mf_Init(cFunction objClass)
		{
			try
			{
				//클래스 초기화
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>클래스 마무리</summary>
		/// <param name="objClass">클래스 객체 인스턴스</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void mf_UnInit(cFunction objClass)
		{
			try
			{
				//클래스 마무리
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
		#region [공용(public) 함수(Method)/API - 클래스 외부로 노출]
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		//명명규칙 - 첫 문자를 "pf_" + 함수명 또는 API 함수명 으로 시작
		//         - 영문 대소문자로 시작하고 함수명이 긴 경우 대소문자 구분해서 명명('_' 사용가능!)
		//▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>공용(public) 함수(Method) 선언 예</summary>
		/// <param name="sStr">공용(public) 함수(Method) 인자 선언 예</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_Hello(string sStr)
		{
			try
			{
				sStr = "Hello...";
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sStr;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>BOM 어플리케이션(Mdi Child Form)을 한번만 실행/종료 하기위해 해쉬 테이블 관리</summary>
		/// <param name="eAppStatus">BOM 어플리케이션(Mdi Child Form) 실행/종료</param>
		/// <param name="sBomAppName">BOM 어플리케이션(Mdi Child Form) 명칭</param>
		/// <param name="frmApp">BOM 어플리케이션(Mdi Child Form) 객체 핸들</param>
		/// <param name="frmMdiParent">BOM 어플리케이션(Mdi Child Form) 부모 객체 핸들</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_AppBomRun(ComCls.cConst.PE_ARGTYPE_APP_STATUS eAppStatus, string sBomAppName, object frmApp, object frmMdiParent)
		{
			bool bResult = true;
			bool bMenuEnabled = true;

			try
			{
				if (sBomAppName != null)
				{
					//---------------------------------------------------------------------------------------------------
					//BOM 어플리케이션(Mdi Child Form) 실행(해쉬테이블에서 검색)
					//---------------------------------------------------------------------------------------------------
					if (eAppStatus == ComCls.cConst.PE_ARGTYPE_APP_STATUS.RUN)
					{
						if (mv_hashBomApplication.Contains(sBomAppName) == true)
						{
							frmApp = mv_hashBomApplication[sBomAppName];

							((Form)frmApp).WindowState = FormWindowState.Normal;
							((Form)frmApp).Activate();

						}
						else
						{
							if (frmApp != null)
							{
								mv_hashBomApplication.Add(sBomAppName, frmApp);

								if (frmMdiParent != null)
								{
									((Form)frmApp).MdiParent = (Form)frmMdiParent;
								}

								((Form)frmApp).Show();
							}
						}
					}
					//---------------------------------------------------------------------------------------------------
					//BOM 어플리케이션(Mdi Child Form) 종료(해쉬테이블에서 제거)
					//---------------------------------------------------------------------------------------------------
					else
					{
						if (mv_hashBomApplication.Contains(sBomAppName) == true)
						{
							mv_hashBomApplication.Remove(sBomAppName);
						}
					}
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}
			finally
			{
				//메인 프로그램 제외
				if (mv_hashBomApplication.Count - 1 == 0)
				{
					bMenuEnabled = false;
				}

				for (int nNum = 0; nNum < pv_Menu_menuParentForBomClients.DropDownItems.Count; nNum++)
				{
					if (pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.IndexOf("정렬") != -1)
					{
						pv_Menu_menuParentForBomClients.DropDownItems[nNum].Enabled = bMenuEnabled;
						pv_Menu_toolbarMain.Items[nNum].Enabled = bMenuEnabled;
					}

					if (pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.IndexOf("모두") != -1)
					{
						pv_Menu_menuParentForBomClients.DropDownItems[nNum].Enabled = bMenuEnabled;
						pv_Menu_toolbarMain.Items[nNum].Enabled = bMenuEnabled;
					}
				}
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>실행중인 BOM 어플리케이션(Mdi Child Form) 수</summary>
		/// <returns>int</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public int pf_AppBomRunCount()
		{
			int nResult = 0;

			try
			{
				//메인 프로그램 제외
				nResult = mv_hashBomApplication.Count - 1;
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return nResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>메인 어플리케이션을 한번만 실행/종료 하기위해 해쉬 테이블 관리</summary>
		/// <param name="eAppStatus">메인 어플리케이션 실행/종료</param>
		/// <param name="sAppName">메인 어플리케이션 명칭</param>
		/// <param name="frmApp">메인 어플리케이션 객체 핸들</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_AppMainRun(ComCls.cConst.PE_ARGTYPE_APP_STATUS eAppStatus, string sAppName, object frmApp)
		{
			bool bResult = true;
			bool bMenuEnabled = true;

			try
			{
				if (sAppName != null)
				{
					//---------------------------------------------------------------------------------------------------
					//메인 어플리케이션 실행(해쉬테이블에서 검색)
					//---------------------------------------------------------------------------------------------------
					if (eAppStatus == ComCls.cConst.PE_ARGTYPE_APP_STATUS.RUN)
					{
						if (frmApp != null)
						{
							if (mv_hashBomApplication.Contains(sAppName) == true)
							{
								frmApp = mv_hashBomApplication[sAppName];

								((Form)frmApp).Activate();

								bResult = false;
							}
							else
							{
								mv_hashBomApplication.Add(sAppName, frmApp);

								((Form)frmApp).Show();
							}
						}
					}
					//---------------------------------------------------------------------------------------------------
					//메인 어플리케이션 종료(해쉬테이블에서 제거)
					//---------------------------------------------------------------------------------------------------
					else
					{
						if (mv_hashBomApplication.Contains(sAppName) == true)
						{
							mv_hashBomApplication.Remove(sAppName);
						}
					}
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}
			finally
			{
				//메인 프로그램 제외
				if (mv_hashBomApplication.Count - 1 == 0)
				{
					bMenuEnabled = false;
				}

				for (int nNum = 0; nNum < pv_Menu_menuParentForBomClients.DropDownItems.Count; nNum++)
				{
					if (pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.IndexOf("정렬") != -1)
					{
						pv_Menu_menuParentForBomClients.DropDownItems[nNum].Enabled = bMenuEnabled;
						pv_Menu_toolbarMain.Items[nNum].Enabled = bMenuEnabled;
					}

					if (pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.IndexOf("모두") != -1)
					{
						pv_Menu_menuParentForBomClients.DropDownItems[nNum].Enabled = bMenuEnabled;
						pv_Menu_toolbarMain.Items[nNum].Enabled = bMenuEnabled;
					}
				}
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>BOM 어플리케이션(Mdi Child Form) 종료 시 종료 메시지를 호출하고 종료 여부에 따라 Cancel값 지정</summary>
		/// <param name="bExitMsgDispOK">메세지 표시 여부</param>
		/// <param name="sFormTitle">BOM 어플리케이션(Mdi Child Form) 타이틀(메모리 제거용)</param>
		/// <param name="e">BOM 어플리케이션(Mdi Child Form) 종료시 전달되는 인자</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_CheckBomExitMsg(bool bExitMsgDispOK, string sFormTitle, ref FormClosingEventArgs e)
		{
			bool bResult = false;

			try
			{
				//메인 프로그램을 종료하는 경우는 제외
				//즉 메인 프로그램을 종료하는 경우에는 BOM 어플리케이션 무조건 종료
				if (e.CloseReason != CloseReason.MdiFormClosing)
				{
					if (bExitMsgDispOK == true)
					{
						if (MessageBox.Show(string.Format("[{0}] {1}", sFormTitle, ComCls.cConst.PC_MSG_APPBOM_EXIT), ComCls.cConst.PC_MSG_APPBOM_EXIT_TITLE,
											MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
						{
							//폼 닫기 취소
							bResult = true;
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				e.Cancel = bResult;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰에서 선택된 모든 셀을 해제하고 특정 행을 선택</summary>
		/// <param name="oDataGridView">데이터그리드뷰 객체 핸들</param>
		/// <param name="nSelectRow">데이터그리드뷰에서 선택할 행번호</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_DataGridViewAllUnSelectCell(DataGridView oDataGridView, int nSelectRow)
		{
			try
			{
				for (int nNum = oDataGridView.SelectedCells.Count - 1; nNum >= 0; nNum--)
				{
					oDataGridView.SelectedCells[nNum].Selected = false;
				}

				if (nSelectRow >= 0 && nSelectRow < oDataGridView.Rows.Count)
				{
					oDataGridView.Rows[nSelectRow].Selected = true;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰 셀에서 수정작업을 하면 작업모드(CRUD) 컬럼에 작업모드 변경</summary>
		/// <param name="oDataGridView">데이터그리드뷰 객체 핸들</param>
		/// <param name="oDataGridViewCellEventArgs">데이터그리드뷰 셀 수정시 발생하는 이벤트 인자</param>
		/// <param name="nJobModeColIndex">데이터그리드뷰에 작업 모드가 들어있는 컬럼 위치</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_DataGridViewChangeJobModeCell(DataGridView oDataGridView, DataGridViewCellEventArgs oDataGridViewCellEventArgs)//, int nJobModeColIndex)
		{
			int nJobModeColIndex = -1;

			try
			{
				if (this.pv_DataGridView_nJobModeColIndex != -1)
				{
					nJobModeColIndex = this.pv_DataGridView_nJobModeColIndex;

					//---------------------------------------------------------------------------------------------------
					//데이터그리드뷰 셀에서 수정작업을 하면 작업모드(CRUD) 컬럼에 작업모드 변경
					//---------------------------------------------------------------------------------------------------
					if (oDataGridViewCellEventArgs.RowIndex != -1 && oDataGridViewCellEventArgs.ColumnIndex != -1 && oDataGridViewCellEventArgs.ColumnIndex != nJobModeColIndex)
					{
						//현재 행에 작업모드 값이 null인 경우에만 신규 모드로 변경
						if (oDataGridView.Rows[oDataGridViewCellEventArgs.RowIndex].Cells[nJobModeColIndex].Value == null)
						{
							oDataGridView.Rows[oDataGridViewCellEventArgs.RowIndex].Cells[nJobModeColIndex].Value = ComCls.cConst.PC_DB_JOBMODE_CREATE;
						}
						else
						{
							//현재 작업모드가 읽기인 경우에만 수정 모드로 변경
							if (oDataGridView.Rows[oDataGridViewCellEventArgs.RowIndex].Cells[nJobModeColIndex].Value.ToString() == ComCls.cConst.PC_DB_JOBMODE_READ)
							{
								oDataGridView.Rows[oDataGridViewCellEventArgs.RowIndex].Cells[nJobModeColIndex].Value = ComCls.cConst.PC_DB_JOBMODE_UPDATE;
							}
						}

						//if (this.dgvMan.Rows[e.RowIndex].Cells[1].Value.ToString() == "C")
						//{
						//    this.dgvMan.Rows[e.RowIndex].HeaderCell.Value = "추가";
						//}
						//else if (this.dgvMan.Rows[e.RowIndex].Cells[1].Value.ToString() == "U")
						//{
						//    this.dgvMan.Rows[e.RowIndex].HeaderCell.Value = "수정";
						//}
					}
					//else if (e.RowIndex != -1 && e.ColumnIndex != -1 && e.ColumnIndex == 1)
					//{
					//    if (this.dgvMan.Rows[e.RowIndex].Cells[1].Value.ToString() == "R")
					//    {
					//        this.dgvMan.Rows[e.RowIndex].HeaderCell.Value = "";
					//    }
					//}
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰 초기화</summary>
		/// <param name="oDataGridView">데이터그리드뷰 객체 핸들</param>
		/// <param name="nJobModeColIndex">데이터그리드뷰에 작업 모드가 들어있는 컬럼 위치</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_DataGridViewInit(DataGridView oDataGridView, int nJobModeColIndex, bool bRowHeaderAllImageUseOK, bool bRowHeaderReadImageUseOK)
		{
			bool bResult = true;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 객체 태그에 작업 모드(CRUD)를 알려주는 컬럼 위치 저장
				//---------------------------------------------------------------------------------------------------
				this.pv_DataGridView_nJobModeColIndex = nJobModeColIndex;
				this.pv_DataGridView_bRowHeaderAllImageUseOK = bRowHeaderAllImageUseOK;
				this.pv_DataGridView_bRowHeaderReadImageUseOK = bRowHeaderReadImageUseOK;
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 이벤트 핸들러 제거(pf_DataGridViewInit() 함수 반복 호출을 가능하도록)
				//---------------------------------------------------------------------------------------------------
				oDataGridView.CellValueChanged -= new DataGridViewCellEventHandler(pf_DataGridViewInit_oDataGridView_CellValueChanged);
				oDataGridView.RowPostPaint -= new DataGridViewRowPostPaintEventHandler(pf_DataGridViewInit_oDataGridView_RowPostPaint);
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 이벤트 핸들러 등록
				//---------------------------------------------------------------------------------------------------
				oDataGridView.CellValueChanged += new DataGridViewCellEventHandler(pf_DataGridViewInit_oDataGridView_CellValueChanged);
				oDataGridView.RowPostPaint += new DataGridViewRowPostPaintEventHandler(pf_DataGridViewInit_oDataGridView_RowPostPaint);
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰에서 셀값이 변경되면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">데이터그리드뷰 객체 핸들</param>
		/// <param name="e">데이터그리드뷰에서 셀값이 변경되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_DataGridViewInit_oDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
		{
			try
			{
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 셀에서 수정작업을 하면 작업모드(CRUD) 컬럼에 작업모드 변경
				//---------------------------------------------------------------------------------------------------
				if (e.RowIndex != -1 && e.ColumnIndex != -1)
				{
					this.pf_DataGridViewChangeJobModeCell((sender as DataGridView), e);
				}
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰에서 행이 그려지기 시작하면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">데이터그리드뷰 객체 핸들</param>
		/// <param name="e">데이터그리드뷰에서 행이 그려지기 시작하면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_DataGridViewInit_oDataGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
		{
			try
			{
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 셀에서 수정작업을 하면 작업모드(CRUD) 컬럼값에 따라 행 헤더에 이미지 적용
				//---------------------------------------------------------------------------------------------------
				this.pf_DataGridViewRowHeaderImage((sender as DataGridView), e);
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰 행 헤더에 이미지 그리기(CRUD 기준)</summary>
		/// <param name="oDataGridView">데이터드리드뷰 객체 핸들</param>
		/// <param name="eDataGridViewRowPostPaintEventArgs">데이터그리드뷰에 RowPostPaint 이벤트 발생 시 전달되는 인자</param>
		/// <param name="nJobModeColIndex">작업 모드(CRUD)가 저장되어 있는 컬럼 위치</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_DataGridViewRowHeaderImage(DataGridView oDataGridView, DataGridViewRowPostPaintEventArgs eDataGridViewRowPostPaintEventArgs)
		{
			string sJobMode = null;

			Bitmap myBitmap = null;
			Icon myIcon = null;
			Graphics graphics = null;
			Rectangle rectangle;

			int iconHeight = 16;
			int iconWidth = 16;
			int xPosition = 0;
			int yPosition = 0;
			int nJobModeColIndex = -1;

			try
			{
				if (this.pv_DataGridView_bRowHeaderAllImageUseOK == true)
				{
					if (this.pv_DataGridView_nJobModeColIndex >= 0)
					{
						nJobModeColIndex = this.pv_DataGridView_nJobModeColIndex;

						if (oDataGridView != null && oDataGridView.Rows.Count > 0 && nJobModeColIndex >= 0)
						{
							if (oDataGridView.Rows[eDataGridViewRowPostPaintEventArgs.RowIndex].Cells[nJobModeColIndex].Value != null)
							{
								sJobMode = oDataGridView.Rows[eDataGridViewRowPostPaintEventArgs.RowIndex].Cells[nJobModeColIndex].Value.ToString();
							}

							if (sJobMode != null)
							{
								switch (sJobMode.ToUpper())
								{
									case ComCls.cConst.PC_DB_JOBMODE_CREATE:
										myBitmap = new Bitmap(Properties.Resources.Create1_16);

										break;
									case ComCls.cConst.PC_DB_JOBMODE_READ:
										if (this.pv_DataGridView_bRowHeaderReadImageUseOK == true)
										{
											myBitmap = new Bitmap(Properties.Resources.Read1_16);
										}

										break;
									case ComCls.cConst.PC_DB_JOBMODE_UPDATE:
										myBitmap = new Bitmap(Properties.Resources.Update1_16);

										break;
									case ComCls.cConst.PC_DB_JOBMODE_DELETE:
										myBitmap = new Bitmap(Properties.Resources.Delete1_16);

										break;
								}

								if (myBitmap != null)
								{
									myIcon = Icon.FromHandle(myBitmap.GetHicon());

									eDataGridViewRowPostPaintEventArgs.PaintHeader(false);
									graphics = eDataGridViewRowPostPaintEventArgs.Graphics;

									xPosition = eDataGridViewRowPostPaintEventArgs.RowBounds.X + (oDataGridView.RowHeadersWidth / 2);
									yPosition = eDataGridViewRowPostPaintEventArgs.RowBounds.Y + ((oDataGridView.Rows[eDataGridViewRowPostPaintEventArgs.RowIndex].Height - iconHeight) / 2);

									rectangle = new Rectangle(xPosition, yPosition, iconWidth, iconHeight);
									graphics.DrawIcon(myIcon, rectangle);
								}
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>데이터그리드뷰 행 헤더에 이미지 그리기(CRUD 기준)</summary>
		/// <param name="oDataGridView">데이터드리드뷰 객체 핸들</param>
		/// <param name="eDataGridViewRowPostPaintEventArgs">데이터그리드뷰에 RowPostPaint 이벤트 발생 시 전달되는 인자</param>
		/// <param name="nJobModeColIndex">작업 모드(CRUD)가 저장되어 있는 컬럼 위치</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_DataGridViewRowHeaderImage(DataGridView oDataGridView, DataGridViewRowPostPaintEventArgs eDataGridViewRowPostPaintEventArgs, int nJobModeColIndex)
		{
			string sJobMode = null;

			Bitmap myBitmap = null;
			Icon myIcon = null;
			Graphics graphics = null;
			Rectangle rectangle;

			int iconHeight = 16;
			int iconWidth = 16;
			int xPosition = 0;
			int yPosition = 0;

			try
			{
				if (oDataGridView != null && oDataGridView.Rows.Count > 0 && nJobModeColIndex >= 0)
				{
					if (oDataGridView.Rows[eDataGridViewRowPostPaintEventArgs.RowIndex].Cells[nJobModeColIndex].Value != null)
					{
						sJobMode = oDataGridView.Rows[eDataGridViewRowPostPaintEventArgs.RowIndex].Cells[nJobModeColIndex].Value.ToString();
					}

					if (sJobMode != null)
					{
						switch (sJobMode.ToUpper())
						{
							case ComCls.cConst.PC_DB_JOBMODE_CREATE:
								myBitmap = new Bitmap(Properties.Resources.Create1_16);

								break;
							case ComCls.cConst.PC_DB_JOBMODE_READ:
								myBitmap = new Bitmap(Properties.Resources.Read1_16);

								break;
							case ComCls.cConst.PC_DB_JOBMODE_UPDATE:
								myBitmap = new Bitmap(Properties.Resources.Update1_16);

								break;
							case ComCls.cConst.PC_DB_JOBMODE_DELETE:
								myBitmap = new Bitmap(Properties.Resources.Delete1_16);

								break;
						}

						if (myBitmap != null)
						{
							myIcon = Icon.FromHandle(myBitmap.GetHicon());

							eDataGridViewRowPostPaintEventArgs.PaintHeader(false);
							graphics = eDataGridViewRowPostPaintEventArgs.Graphics;

							xPosition = eDataGridViewRowPostPaintEventArgs.RowBounds.X + (oDataGridView.RowHeadersWidth / 2);
							yPosition = eDataGridViewRowPostPaintEventArgs.RowBounds.Y + ((oDataGridView.Rows[eDataGridViewRowPostPaintEventArgs.RowIndex].Height - iconHeight) / 2);

							rectangle = new Rectangle(xPosition, yPosition, iconWidth, iconHeight);
							graphics.DrawIcon(myIcon, rectangle);
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>그리드 내용을 엑셀로 출력</summary>
		/// <param name="oDataGridView">엑셀로 변환할 그리드</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_ExcelFromDataGridView(DataGridView oDataGridView)
		{
			Microsoft.Office.Interop.Excel.Application oXL;			//엑셀어플리케이션
			Microsoft.Office.Interop.Excel._Workbook oWB;			//워크북
			Microsoft.Office.Interop.Excel._Worksheet oSheet;		//시트
			string oGridColType;
			string[] colHeader;
			object[,] saNames;

			try
			{
				//엑셀 시작 및 어플리케이션 오브젝트를 불러온다.
				oXL = new Microsoft.Office.Interop.Excel.Application();
				oXL.Visible = true;

				//새로운 워크북을 불러온다.
				oWB = (Microsoft.Office.Interop.Excel._Workbook)(oXL.Workbooks.Add(Missing.Value));
				oSheet = (Microsoft.Office.Interop.Excel._Worksheet)oWB.ActiveSheet;

				//헤더를 추가
				int k = 0;
				colHeader = new string[oDataGridView.ColumnCount];

				for (int nCol = 0; nCol < oDataGridView.Columns.Count; nCol++)
				{
					oSheet.Cells[1, nCol + 1] = oDataGridView.Columns[nCol].HeaderText;

					k = nCol + 65;
					colHeader[nCol] = Convert.ToString((char)k);
				}

				//헤더의 텍스트 설정(굵게, 가운데 정렬)
				oSheet.get_Range("A1", colHeader[colHeader.Length - 1] + "1").Font.Bold = true;
				oSheet.get_Range("A1", colHeader[colHeader.Length - 1] + "1").VerticalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
				oSheet.get_Range("A1", colHeader[colHeader.Length - 1] + "1").HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;

				//Cell의 여러 데이터값을 배열로 생성 - Object [행, 열] 형태
				saNames = new object[oDataGridView.RowCount, oDataGridView.ColumnCount];

				for (int nRow = 0; nRow < oDataGridView.RowCount; nRow++)
				{
					for (int nCol = 0; nCol < oDataGridView.ColumnCount; nCol++)
					{
						oGridColType = oDataGridView.Rows[nRow].Cells[nCol].ValueType.Name;

						if (oGridColType == "String")
							saNames[nRow, nCol] = "'" + oDataGridView.Rows[nRow].Cells[nCol].Value.ToString();
						else
							saNames[nRow, nCol] = oDataGridView.Rows[nRow].Cells[nCol].Value;
					}
				}

				//배열에 생성된 데이터값들을 엑셀에 출력
				oSheet.get_Range(colHeader[0] + "2", colHeader[colHeader.Length - 1] + (oDataGridView.RowCount + 1)).Value2 = saNames;

				oXL.Visible = true;
				oXL.UserControl = true;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>파일 업/다운로드</summary>
		/// <param name="eProtocol">파일 업/다운로드 프로토콜(HTTP/FTP)</param>
		/// <param name="eType">파일 업/다운로드 방법</param>
		/// <param name="sWebServerPath">파일 업/다운로드할 서버 경로</param>
		/// <param name="sWebServerFileNameReName">파일 업/다운로드할 변경할 파일명</param>
		/// <param name="sFileNamePath">파일 업/다운로드할 로컬 파일 경로</param>
		/// <param name="sUserID">사용자 계정(FTP인 경우만)</param>
		/// <param name="sPassword">사용자 계정 비밀번호(FTP인 경우만)</param>
		/// <param name="bAutoClose">파일 업/다운로드 완료시 창 자동닫기 여부</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_FileUpDownLoad(ComCls.cConst.PE_FILE_UPDOWN_PROTOCOL eProtocol, ComCls.cConst.PE_FILE_UPDOWN_TYPE eType, string sWebServerPath, string sWebServerFileNameReName, string sFileNamePath, string sUserID, string sPassword, bool bAutoClose)
		{
			frmFileUpDownLoad frmUpDown = null;
			FileInfo oFileInfo = null;

			bool bOK = true;

			try
			{
				frmUpDown = new frmFileUpDownLoad();

				if (frmUpDown != null)
				{
					frmUpDown.OnUpDownloadFileCompleted += new frmFileUpDownLoad.UpDownloadFileCompleted(pf_frmUpDown_OnUpDownloadFileCompleted);

					if (eProtocol == ComCls.cConst.PE_FILE_UPDOWN_PROTOCOL.HTTP &&
						eType == ComCls.cConst.PE_FILE_UPDOWN_TYPE.UPLOAD)
					{
						if (File.Exists(sFileNamePath) == true)
						{
							oFileInfo = new FileInfo(sFileNamePath);
							
							if (oFileInfo.Length / 1024000 >= 30)
							{
								bOK = false;

								MessageBox.Show(ComCls.cConst.PC_ERROR_FILE_UPLOAD_HTTP_MAXSIZE, ComCls.cConst.PC_ERROR_FILE_UPLOAD_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
							}
						}
						else bOK = false;
					}

					if (bOK == true)
					{
						if (frmUpDown.pf_Init(eProtocol, eType, sWebServerPath, sWebServerFileNameReName, sFileNamePath, sUserID, sPassword, bAutoClose) == true)
						{
							frmUpDown.ShowDialog();
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>파일 업/다운로드 완료 이벤트</summary>
		/// <param name="sender">이벤트 발생 객체</param>
		/// <param name="eProtocol">파일 업/다운로드 프로토콜(HTTP/FTP)</param>
		/// <param name="eType">파일 업/다운로드 방법</param>
		/// <param name="eStatus">파일 업/다운로드 상태(완료/취소)</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_frmUpDown_OnUpDownloadFileCompleted(object sender, cConst.pv_strucFileUpDownloadInfo strucFileUpDownloadInfo)
		{
			try
			{
				this.OnUpDownloadFileCompleted(sender, strucFileUpDownloadInfo);
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>FTP 서버에서 특정 파일을 지우기</summary>
		/// <param name="sFtpServerFilePath">FTP 서버에 있는 파일명(경로포함)</param>
		/// <param name="sUserID">FTP 사용자 계정</param>
		/// <param name="sPassword">FTP 사용자 계정 비밀번호</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_FtpDeleteFile(string sFtpServerFilePath, string sUserID, string sPassword)
		{
			bool bResult = false;
			FtpWebRequest requestFtp = null;
			FtpWebResponse responseFtp = null;

			try
			{
				requestFtp = (FtpWebRequest)WebRequest.Create(sFtpServerFilePath);

				requestFtp.Credentials = new NetworkCredential(sUserID, sPassword);
				requestFtp.Method = WebRequestMethods.Ftp.DeleteFile;

				responseFtp = (FtpWebResponse)requestFtp.GetResponse();

				responseFtp.Close();

				bResult = true;
			}
			catch //(Exception ex)
			{
				bResult = false;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>FTP 서버에서 특정 파일의 크기를 구하기</summary>
		/// <param name="sFtpServerFilePath">FTP 서버에 있는 파일명(경로포함)</param>
		/// <param name="sUserID">FTP 사용자 계정</param>
		/// <param name="sPassword">FTP 사용자 계정 비밀번호</param>
		/// <param name="nFileSize">파일 크기 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_FtpGetFileSize(string sFtpServerFilePath, string sUserID, string sPassword, ref long nFileSize)
		{
			bool bResult = false;
			FtpWebRequest requestFtp = null;
			FtpWebResponse responseFtp = null;

			try
			{
				requestFtp = (FtpWebRequest)WebRequest.Create(sFtpServerFilePath);

				requestFtp.Credentials = new NetworkCredential(sUserID, sPassword);
				requestFtp.Method = WebRequestMethods.Ftp.GetFileSize;

				responseFtp = (FtpWebResponse)requestFtp.GetResponse();

				nFileSize = responseFtp.ContentLength;

				responseFtp.Close();

				bResult = true;
			}
			catch //(Exception ex)
			{
				bResult = false;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>메인 어플리케이션 어셈블리 버전정보 읽기</summary>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_GetAppAssemblyVersion()
		{
			string sResult = "x.x.x.x";

			try
			{
				Assembly oAssembly = Assembly.GetExecutingAssembly();
				Version oVersion = oAssembly.GetName().Version;

				//---------------------------------------------------------------------------------------------------
				//주버전.부버전.빌드번호.수정번호
				//---------------------------------------------------------------------------------------------------
				sResult = string.Format("ver {0}.{1}.{2}.{3}", oVersion.Major, oVersion.Minor, oVersion.Build, oVersion.Revision);
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>BOM 어플리케이션(Mdi Child Form)을 실행할 메뉴를 지정한 부모메뉴 아래에 등록</summary>
		/// <param name="menuParent">부모 메뉴 핸들</param>
		/// <param name="frmBomApp">실행할 BOM 어플리케이션 타이틀 배열</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_MenuAppendBomApp(ToolStripMenuItem menuParent, string[] sMenuBomApps, pv_Menu_delMenuBomApp delBomApp)
		{
			bool bResult = false;
			ToolStripItem menuToolStripItem = null;

			try
			{
				if (menuParent != null && sMenuBomApps != null && delBomApp != null)
				{
					//menuParent 부모 메뉴 초기화
					menuParent.DropDownItems.Clear();

					//menuParent 부모 메뉴에 BOM 어플리케이션(Mdi Child Form)들 다시 추가
					for (int nNum = 0; nNum < sMenuBomApps.Length; nNum++)
					{
						//메뉴에 실행할 BOM 어플리케이션(Mdi Child Form) 타이틀 등록
						menuToolStripItem = menuParent.DropDownItems.Add(string.Format("{0}", sMenuBomApps[nNum]));

						if (menuToolStripItem != null)
						{
							//메뉴를 클릭하는 경우 호출할 이벤트 연결
							menuToolStripItem.Click += new EventHandler(pf_MenuBomApp_Click);
							menuToolStripItem.Tag = delBomApp;
						}
					}

					if (menuToolStripItem != null)
					{
						bResult = true;
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>History 메뉴를 클릭하는 경우 호출되는 이벤트 함수</summary>
		/// <param name="sender">클릭한 History 메뉴 핸들</param>
		/// <param name="e">클릭한 History 메뉴에 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_MenuBomApp_Click(object sender, EventArgs e)
		{
			pv_Menu_delMenuBomApp delBomApp = null;

			try
			{
				if (sender != null)
				{
					//클릭한 메뉴 태그에 저장된 델리게이트 함수를 복원
					delBomApp = ((sender as ToolStripItem).Tag as pv_Menu_delMenuBomApp);

					if (delBomApp != null)
					{
						//메뉴를 클릭하면 BOM 어플리케이션(Mdi Child Form) 인스턴스를 생성하고 실행
						delBomApp((sender as ToolStripItem).Text);
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
				//throw new NotImplementedException();
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>BOM 어플리케이션(Mdi Child Form) 실행 시 지정한 부모메뉴 아래에 History 메뉴로 등록(자동으로 번호 부여)</summary>
		/// <param name="menuParent">부모 메뉴 핸들</param>
		/// <param name="frmBomApp">실행한 BOM 어플리케이션(Mdi Child Form) 핸들</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_MenuHistoryAppendBomApp(ToolStripMenuItem menuParent, Form frmBomApp)
		{
			bool bResult = true;
			bool bFindOK = false;
			string sMenuTitle = null;
			int nMenuNumber = 0;
			ToolStripItem menuToolStripItem = null;

			try
			{
				//BOM 어플리케이션(Mdi Child Form)이 닫히는 경우 null이 전달 됨
				if (menuParent != null && frmBomApp != null)
				{
					//실행된 BOM 어플리케이션(Mdi Child Form)이 메뉴에 등록되어 있는지 파악
					for (int nNum = this.pv_Menu_nInitNumber; nNum < menuParent.DropDownItems.Count; nNum++)
					{
						//메뉴 타이틀 앞에 번호 제거
						sMenuTitle = menuParent.DropDownItems[nNum].Text.Substring(menuParent.DropDownItems[nNum].Text.IndexOf(" ") + 1);

						//실행된 BOM 어플리케이션(Mdi Child Form)이 메뉴에 등록된 경우
						if (sMenuTitle != null && sMenuTitle == frmBomApp.Text)
						{
							bFindOK = true;

							break;
						}
					}

					//메뉴가 등록되지 않은 경우
					if (bFindOK == false)
					{
						//메뉴 처음 등록하는 경우
						if (this.pv_Menu_bNumberInitOK == false)
						{
							this.pv_Menu_bNumberInitOK = true;
							this.pv_Menu_nInitNumber = menuParent.DropDownItems.Count;
							//pv_menuParentForBomClients = menuParent;
						}

						//메뉴 번호 증가
						nMenuNumber = menuParent.DropDownItems.Count + 1 - this.pv_Menu_nInitNumber;

						//메뉴에 실행된 BOM 어플리케이션(Mdi Child Form) 타이틀 등록
						menuToolStripItem = menuParent.DropDownItems.Add(string.Format("{0} {1}", nMenuNumber, frmBomApp.Text));

						if (menuToolStripItem != null)
						{
							//메뉴를 클릭하는 경우 호출할 이벤트 연결
							menuToolStripItem.Click += new EventHandler(pf_MenuHistoryBomApp_Click);

							//메뉴에 연결된 폼이 닫히는 경우 호출할 이벤트 연결
							frmBomApp.FormClosed += new FormClosedEventHandler(pf_MenuHistoryLinkedForm_FormClosed);
						}
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>History 메뉴를 클릭하는 경우 호출되는 이벤트 함수</summary>
		/// <param name="sender">클릭한 History 메뉴 핸들</param>
		/// <param name="e">클릭한 History 메뉴에 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_MenuHistoryBomApp_Click(object sender, EventArgs e)
		{
			try
			{
				//메뉴를 선택하면 연결된 BOM 어플리케이션(Mdi Child Form)을 찾아 포커스 주기
				this.pf_MenuHistorySelectToFocus(sender as ToolStripMenuItem);
			}
			catch (Exception ex)
			{
				throw ex;
				//throw new NotImplementedException();
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>BOM 어플리케이션(Mdi Child Form)이 닫히면 연결된 History 메뉴를 찾아 삭제하고 나머지 메뉴에 번호 새로 부여</summary>
		/// <param name="frmBomApp">닫힌 BOM 어플리케이션(Mdi Child Form) 객체</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_MenuHistoryDeleteCloseForm(Form frmBomApp)
		{
			bool bResult = true;
			string sMenuTitle = null;
			int nMenuNumber = 0;

			try
			{
				if (frmBomApp != null && pv_Menu_menuParentForBomClients != null)
				{
					//실행된 BOM 어플리케이션(Mdi Child Form)이 메뉴에 등록되어 있는지 파악
					for (int nNum = this.pv_Menu_nInitNumber; nNum < pv_Menu_menuParentForBomClients.DropDownItems.Count; nNum++)
					{
						//메뉴 타이틀 앞에 번호 제거
						sMenuTitle = pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.Substring(pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.IndexOf(" ") + 1);

						//실행된 BOM 어플리케이션(Mdi Child Form)이 메뉴에 등록된 경우
						if (sMenuTitle != null && sMenuTitle == frmBomApp.Text)
						{
							//메뉴를 클릭하는 경우의 이벤트 해제
							pv_Menu_menuParentForBomClients.DropDownItems[nNum].Click -= new EventHandler(pf_MenuHistoryBomApp_Click);

							//메뉴에 연결된 BOM 어플리케이션(Mdi Child Form)이 닫히는 경우의 이벤트 해제
							frmBomApp.FormClosed -= new FormClosedEventHandler(pf_MenuHistoryLinkedForm_FormClosed);

							//종료된 BOM 어플리케이션(Mdi Child Form)과 연결된 메뉴 제거
							pv_Menu_menuParentForBomClients.DropDownItems.RemoveAt(nNum);

							break;
						}
					}

					//남은 메뉴 번호 다시 매기기
					for (int nNum = this.pv_Menu_nInitNumber; nNum < pv_Menu_menuParentForBomClients.DropDownItems.Count; nNum++)
					{
						//메뉴 타이틀 앞에 번호 제거
						sMenuTitle = pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.Substring(pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text.IndexOf(" ") + 1);

						//메뉴 번호 증가
						nMenuNumber = nNum + 1 - this.pv_Menu_nInitNumber;

						//메뉴 타이틀 변경
						pv_Menu_menuParentForBomClients.DropDownItems[nNum].Text = string.Format("{0} {1}", nMenuNumber, sMenuTitle);
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>History 메뉴에 연결된 BOM 어플리케이션(Mdi Child Form)이 닫히는 경우 호출되는 이벤트 함수</summary>
		/// <param name="sender">닫힌 BOM 어플리케이션(Mdi Child Form) 객체</param>
		/// <param name="e">닫힌 BOM 어플리케이션(Mdi Child Form) 객체에 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_MenuHistoryLinkedForm_FormClosed(object sender, FormClosedEventArgs e)
		{
			try
			{
				//닫힌 BOM 어플리케이션(Mdi Child Form)에 연결된 메뉴를 찾아 삭제하고 나머지 메뉴에 번호 새로 부여
				this.pf_MenuHistoryDeleteCloseForm(sender as Form);
			}
			catch (Exception ex)
			{
				throw ex;
				//throw new NotImplementedException();
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>History 메뉴를 선택하면 연결된 BOM 어플리케이션(Mdi Child Form)을 찾아 포커스 주기</summary>
		/// <param name="menuBomApp">클릭한 History 메뉴 핸들</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_MenuHistorySelectToFocus(ToolStripMenuItem menuBomApp)
		{
			bool bResult = true;
			string sMenuTitle = null;

			try
			{
				//메뉴 타이틀 앞에 번호 제거
				sMenuTitle = menuBomApp.Text.Substring(menuBomApp.Text.IndexOf(" ") + 1);

				if (sMenuTitle != null)
				{
					//메뉴 선택 시 해당 BOM 어플리케이션을 찾아서 포커스 주기
					this.pf_AppBomRun(ComCls.cConst.PE_ARGTYPE_APP_STATUS.RUN, sMenuTitle, null, null);
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>//실행된 BOM Client를 메뉴로 등록할 메인 폼의 부모 메뉴 & 툴바 핸들 연결(cFunction 쪽에서 작업해야 하므로 필요)</summary>
		/// <param name="sAppName">메인 어플리케이션 명칭</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_SetBomMainMenuAndToolbar(ToolStripMenuItem oToolStripMenuItem, ToolStrip oToolStrip)
		{
			try
			{
				pv_Menu_menuParentForBomClients = oToolStripMenuItem;
				pv_Menu_toolbarMain = oToolStrip;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>모니터 해상도가 frmForm 사이즈 보다 작은 경우 frmForm 사이즈를 스크린 사이즈에 맞춘다</summary>
		/// <param name="frmForm">폼 객체</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_SetFormSize(object frmForm)
		{
			bool bXChangeSizeOK = false;
			bool bYChangeSizeOK = false;

			try
			{
				if (Screen.GetWorkingArea((Control)frmForm).Width < ((Form)frmForm).Width) bXChangeSizeOK = true;
				if (Screen.GetWorkingArea((Control)frmForm).Height < ((Form)frmForm).Height) bYChangeSizeOK = true;

				if (bXChangeSizeOK == true || bYChangeSizeOK == true)
				{
					((Form)frmForm).Width = Screen.GetWorkingArea((Control)frmForm).Width;
					((Form)frmForm).Height = Screen.GetWorkingArea((Control)frmForm).Height;
				}
				((Form)frmForm).Left = Screen.GetWorkingArea((Control)frmForm).Left;
				((Form)frmForm).Top = Screen.GetWorkingArea((Control)frmForm).Top;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>Tree List View 아이템 구성-XML 사용(스택 오버플로우 발생 가능 없음)</summary>
		/// <param name="oTreeListView">트리 리스트 뷰 객체</param>
		/// <param name="sTreeItemRootID">루트 아이템 ID</param>
		/// <param name="oTreeItemParent">부모 아이템 객체</param>
		/// <param name="oDataRow">등록할 아이템 행 정보</param>
		/// <param name="saDataSubItemsKey">등록할 아이템의 서브아이템의 Key 배열 정보</param>
		/// <param name="saDataSubItemsText">등록할 아이템의 서브아이템의 Text 배열 정보</param>
		/// <param name="nRowIndex">다음 아이템 행</param>
		/// <param name="bRootItemCreateOK">루트에 아이템을 생성할지 여부</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeAddItem(TreeListView oTreeListView, string sTreeItemRootID, ref TreeListViewItem oTreeItemParent, DataRow oDataRow, string[] saDataSubItemsKey, string[] saDataSubItemsText, ref int nRowIndex, bool bRootItemCreateOK)
		{
			bool bResult = false;
			TreeListViewItem tlviCurTreeItem = null;
			int nItemIndex = -1;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//TreeList Root 생성(a.OBJECTID, a.PAR_OBJECTID, a.GRP_OBJECTID, a.ID, ' ' AS PATTERN, a.KNAME, a.CID)
				//---------------------------------------------------------------------------------------------------
				if (oDataRow != null && oDataRow[1].ToString() == sTreeItemRootID && bRootItemCreateOK == true)
				{
					oTreeItemParent = oTreeListView.Items.Add(string.Format("{0}({1})", oDataRow[5].ToString(), oDataRow[3].ToString()));
					oTreeItemParent.Name = oDataRow[0].ToString();
					oTreeItemParent.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(oDataRow[6].ToString()));
					oTreeItemParent.Tag = oDataRow;

					this.pf_TreeAddSubItems(ref oTreeItemParent, saDataSubItemsKey, saDataSubItemsText);

					nRowIndex++;
					bResult = true;
				}
				//---------------------------------------------------------------------------------------------------
				//TreeList Root Child 생성
				//---------------------------------------------------------------------------------------------------
				else
				{
					//---------------------------------------------------------------------------------------------------
					//현재 트리리스트 아이템의 키와 등록할 노드의 부모 키 비교(현재 등록되는 아이템은 oTreeItemParent 가 부모가 되므로...)
					//---------------------------------------------------------------------------------------------------
					if (oTreeItemParent != null && oTreeItemParent.Name == oDataRow[1].ToString())
					{
						//---------------------------------------------------------------------------------------------------
						//oTreeItemParent를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						tlviCurTreeItem = oTreeItemParent.Items.Add(string.Format("{0}({1})", oDataRow[5].ToString(), oDataRow[3].ToString()));
						tlviCurTreeItem.Name = oDataRow[0].ToString();
						tlviCurTreeItem.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(oDataRow[6].ToString()));
						tlviCurTreeItem.Tag = oDataRow;

						this.pf_TreeAddSubItems(ref tlviCurTreeItem, saDataSubItemsKey, saDataSubItemsText);

						nRowIndex++;
						bResult = true;
						//---------------------------------------------------------------------------------------------------
					}
					//---------------------------------------------------------------------------------------------------
					//트리리스트 아이템의 키와 등록할 아이템의 부모 키 비교(현재 등록되는 아이템은 oTreeItemParent 가 부모가 아니므로...)
					//---------------------------------------------------------------------------------------------------
					else
					{
						this.pf_TreeItemContains(oTreeItemParent, oDataRow[1].ToString(), ref nItemIndex);

						//---------------------------------------------------------------------------------------------------
						//oTreeItemParent.Items[nItemIndex]를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						if (oTreeItemParent != null && nItemIndex > -1)
						{
							tlviCurTreeItem = oTreeItemParent.Items[nItemIndex].Items.Add(string.Format("{0}({1})", oDataRow[5].ToString(), oDataRow[3].ToString()));
							tlviCurTreeItem.Name = oDataRow[0].ToString();
							tlviCurTreeItem.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(oDataRow[6].ToString()));
							tlviCurTreeItem.Tag = oDataRow;

							this.pf_TreeAddSubItems(ref tlviCurTreeItem, saDataSubItemsKey, saDataSubItemsText);

							nRowIndex++;
							oTreeItemParent = oTreeItemParent.Items[nItemIndex];
							bResult = true;
							//---------------------------------------------------------------------------------------------------
						}
						else
						{
							//---------------------------------------------------------------------------------------------------
							//트리리스트 아이템이 확장된경우 현재 노드 ID가 루트인 경우 이미 트리에 있으므로 스킵 시킴
							//---------------------------------------------------------------------------------------------------
							if (oTreeItemParent != null && oDataRow[0].ToString() == sTreeItemRootID)
							{
								nRowIndex++;
								bResult = true;
							}
							else
							{
								//---------------------------------------------------------------------------------------------------
								//oTreeItemParent.Items[nItemIndex]를 부모로 찾지못한 경우 상위 부모를 전달해서 등록
								//---------------------------------------------------------------------------------------------------
								if (oTreeItemParent != null && oTreeItemParent.Parent != null)
								{
									oTreeItemParent = oTreeItemParent.Parent;
									bResult = true;
								}
							}
							//---------------------------------------------------------------------------------------------------
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>Tree List View 아이템 구성-PARSE 사용(스택 오버플로우 발생 가능 없음)</summary>
		/// <param name="oTreeListView">트리 리스트 뷰 객체</param>
		/// <param name="sTreeItemRootID">루트 아이템 ID</param>
		/// <param name="oTreeItemParent">부모 아이템 객체</param>
		/// <param name="saDataSetCols">등록할 아이템 배열 정보</param>
		/// <param name="saDataSubItemsKey">등록할 아이템의 서브아이템의 Key 배열 정보</param>
		/// <param name="saDataSubItemsText">등록할 아이템의 서브아이템의 Text 배열 정보</param>
		/// <param name="nRowIndex">다음 아이템 행</param>
		/// <param name="bRootItemCreateOK">루트에 아이템을 생성할지 여부</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeAddItem(TreeListView oTreeListView, string sTreeItemRootID, ref TreeListViewItem oTreeItemParent, string[] saDataSetCols, string[] saDataSubItemsKey, string[] saDataSubItemsText, ref int nRowIndex, bool bRootItemCreateOK)
		{
			bool bResult = false;
			TreeListViewItem tlviCurTreeItem = null;
			int nItemIndex = -1;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//TreeList Root 생성(a.OBJECTID, a.PAR_OBJECTID, a.GRP_OBJECTID, a.ID, ' ' AS PATTERN, a.KNAME, a.CID)
				//---------------------------------------------------------------------------------------------------
				if (saDataSetCols != null && saDataSetCols[1] == sTreeItemRootID && bRootItemCreateOK == true)
				{
					oTreeItemParent = oTreeListView.Items.Add(string.Format("{0}({1})", saDataSetCols[5], saDataSetCols[3]));
					oTreeItemParent.Name = saDataSetCols[0];
					oTreeItemParent.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(saDataSetCols[6]));
					oTreeItemParent.Tag = saDataSetCols;

					this.pf_TreeAddSubItems(ref oTreeItemParent, saDataSubItemsKey, saDataSubItemsText);

					nRowIndex++;
					bResult = true;
				}
				//---------------------------------------------------------------------------------------------------
				//TreeList Root Child 생성
				//---------------------------------------------------------------------------------------------------
				else
				{
					//---------------------------------------------------------------------------------------------------
					//현재 트리리스트 아이템의 키와 등록할 노드의 부모 키 비교(현재 등록되는 아이템은 oTreeItemParent 가 부모가 되므로...)
					//---------------------------------------------------------------------------------------------------
					if (oTreeItemParent != null && oTreeItemParent.Name == saDataSetCols[1])
					{
						//---------------------------------------------------------------------------------------------------
						//oTreeItemParent를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						tlviCurTreeItem = oTreeItemParent.Items.Add(string.Format("{0}({1})", saDataSetCols[5], saDataSetCols[3]));
						tlviCurTreeItem.Name = saDataSetCols[0];
						tlviCurTreeItem.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(saDataSetCols[6]));
						tlviCurTreeItem.Tag = saDataSetCols;

						this.pf_TreeAddSubItems(ref tlviCurTreeItem, saDataSubItemsKey, saDataSubItemsText);

						nRowIndex++;
						bResult = true;
						//---------------------------------------------------------------------------------------------------
					}
					//---------------------------------------------------------------------------------------------------
					//트리리스트 아이템의 키와 등록할 아이템의 부모 키 비교(현재 등록되는 아이템은 oTreeItemParent 가 부모가 아니므로...)
					//---------------------------------------------------------------------------------------------------
					else
					{
						this.pf_TreeItemContains(oTreeItemParent, saDataSetCols[1], ref nItemIndex);

						//---------------------------------------------------------------------------------------------------
						//oTreeItemParent.Items[nItemIndex]를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						if (oTreeItemParent != null && nItemIndex > -1)
						{
							tlviCurTreeItem = oTreeItemParent.Items[nItemIndex].Items.Add(string.Format("{0}({1})", saDataSetCols[5], saDataSetCols[3]));
							tlviCurTreeItem.Name = saDataSetCols[0];
							tlviCurTreeItem.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(saDataSetCols[6]));
							tlviCurTreeItem.Tag = saDataSetCols;

							this.pf_TreeAddSubItems(ref tlviCurTreeItem, saDataSubItemsKey, saDataSubItemsText);

							nRowIndex++;
							oTreeItemParent = oTreeItemParent.Items[nItemIndex];
							bResult = true;
							//---------------------------------------------------------------------------------------------------
						}
						else
						{
							//---------------------------------------------------------------------------------------------------
							//트리리스트 아이템이 확장된경우 현재 노드 ID가 루트인 경우 이미 트리에 있으므로 스킵 시킴
							//---------------------------------------------------------------------------------------------------
							if (oTreeItemParent != null && saDataSetCols[0] == sTreeItemRootID)
							{
								nRowIndex++;
								bResult = true;
							}
							else
							{
								//---------------------------------------------------------------------------------------------------
								//oTreeItemParent.Items[nItemIndex]를 부모로 찾지못한 경우 상위 부모를 전달해서 등록
								//---------------------------------------------------------------------------------------------------
								if (oTreeItemParent != null && oTreeItemParent.Parent != null)
								{
									oTreeItemParent = oTreeItemParent.Parent;
									bResult = true;
								}
							}
							//---------------------------------------------------------------------------------------------------
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>Tree 노드 구성-XML 사용(스택 오버플로우 발생 가능 없음)</summary>
		/// <param name="oTreeView">트리 객체</param>
		/// <param name="sTreeNodeRootID">트리 루트 ID</param>
		/// <param name="oTreeNodeParent">부모 노드 객체</param>
		/// <param name="oDataRow">등록할 노드 행 정보</param>
		/// <param name="nRowIndex">다음 노드 행</param>
		/// <param name="bRootNodeCreateOK">루트에 노드를 생성할지 여부</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeAddNode(TreeView oTreeView, string sTreeNodeRootID, ref TreeNode oTreeNodeParent, DataRow oDataRow, ref int nRowIndex, bool bRootNodeCreateOK)
		{
			bool bResult = false;
			TreeNode tnCurTreeNode = null;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//Tree Root 생성(a.OBJECTID, a.PAR_OBJECTID, a.GRP_OBJECTID, a.ID, ' ' AS PATTERN, a.KNAME, a.CID)
				//---------------------------------------------------------------------------------------------------
				if (oDataRow != null && oDataRow[1].ToString() == sTreeNodeRootID && bRootNodeCreateOK == true)
				{
					oTreeNodeParent = oTreeView.Nodes.Add(oDataRow[0].ToString(), string.Format("{0}({1})", oDataRow[5].ToString(), oDataRow[3].ToString()));
					oTreeNodeParent.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(oDataRow[6].ToString()));
					oTreeNodeParent.SelectedImageIndex = oTreeNodeParent.ImageIndex + 1;
					oTreeNodeParent.Tag = oDataRow;

					nRowIndex++;
					bResult = true;
				}
				//---------------------------------------------------------------------------------------------------
				//Tree Root Child 생성
				//---------------------------------------------------------------------------------------------------
				else
				{
					//---------------------------------------------------------------------------------------------------
					//현재 노드의 키와 등록할 노드의 부모 키 비교(현재 등록되는 노드는 tnNode 가 부모가 되므로...)
					//---------------------------------------------------------------------------------------------------
					if (oTreeNodeParent != null && oTreeNodeParent.Name == oDataRow[1].ToString())
					{
						//---------------------------------------------------------------------------------------------------
						//tnNode를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						tnCurTreeNode = oTreeNodeParent.Nodes.Add(oDataRow[0].ToString(), string.Format("{0}({1})", oDataRow[5].ToString(), oDataRow[3].ToString()));
						tnCurTreeNode.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(oDataRow[6].ToString()));
						tnCurTreeNode.SelectedImageIndex = tnCurTreeNode.ImageIndex + 1;
						tnCurTreeNode.Tag = oDataRow;

						nRowIndex++;
						bResult = true;
						//---------------------------------------------------------------------------------------------------
					}
					//---------------------------------------------------------------------------------------------------
					//현재 노드의 키와 등록할 노드의 부모 키 비교(현재 등록되는 노드는 tnNode 가 부모가 아니므로...)
					//---------------------------------------------------------------------------------------------------
					else
					{
						//---------------------------------------------------------------------------------------------------
						//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						if (oTreeNodeParent != null && oTreeNodeParent.Nodes.ContainsKey(oDataRow[1].ToString()) == true)
						{
							tnCurTreeNode = oTreeNodeParent.Nodes[oDataRow[1].ToString()].Nodes.Add(oDataRow[0].ToString(), string.Format("{0}({1})", oDataRow[5].ToString(), oDataRow[3].ToString()));
							tnCurTreeNode.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(oDataRow[6].ToString()));
							tnCurTreeNode.SelectedImageIndex = tnCurTreeNode.ImageIndex + 1;
							tnCurTreeNode.Tag = oDataRow;

							nRowIndex++;
							oTreeNodeParent = oTreeNodeParent.Nodes[oDataRow[1].ToString()];
							bResult = true;
							//---------------------------------------------------------------------------------------------------
						}
						else
						{
							//---------------------------------------------------------------------------------------------------
							//트리노드가 확장된경우 현재 노드 ID가 루트인 경우 이미 트리에 있으므로 스킵 시킴
							//---------------------------------------------------------------------------------------------------
							if (oTreeNodeParent != null && oDataRow[0].ToString() == sTreeNodeRootID)
							{
								nRowIndex++;
								bResult = true;
							}
							else
							{
								//---------------------------------------------------------------------------------------------------
								//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 찾지못한 경우 상위 부모를 전달해서 등록
								//---------------------------------------------------------------------------------------------------
								if (oTreeNodeParent != null && oTreeNodeParent.Parent != null)
								{
									oTreeNodeParent = oTreeNodeParent.Parent;
									bResult = true;
								}
							}
							//---------------------------------------------------------------------------------------------------
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>Tree 노드 구성-PARSE 사용(스택 오버플로우 발생 가능 없음)</summary>
		/// <param name="oTreeView">트리 객체</param>
		/// <param name="sTreeNodeRootID">트리 루트 ID</param>
		/// <param name="oTreeNodeParent">부모 노드 객체</param>
		/// <param name="saDataSetCols">등록할 노드 배열 정보</param>
		/// <param name="nRowIndex">다음 노드 행</param>
		/// <param name="bRootNodeCreateOK">루트에 노드를 생성할지 여부</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeAddNode(TreeView oTreeView, string sTreeNodeRootID, ref TreeNode oTreeNodeParent, string[] saDataSetCols, ref int nRowIndex, bool bRootNodeCreateOK)
		{
			bool bResult = false;
			TreeNode tnCurTreeNode = null;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//Tree Root 생성(a.OBJECTID, a.PAR_OBJECTID, a.GRP_OBJECTID, a.ID, ' ' AS PATTERN, a.KNAME, a.CID)
				//---------------------------------------------------------------------------------------------------
				if (saDataSetCols != null && saDataSetCols[1] == sTreeNodeRootID && bRootNodeCreateOK == true)
				{
					oTreeNodeParent = oTreeView.Nodes.Add(saDataSetCols[0], string.Format("{0}({1})", saDataSetCols[5], saDataSetCols[3]));
					oTreeNodeParent.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(saDataSetCols[6]));
					oTreeNodeParent.SelectedImageIndex = oTreeNodeParent.ImageIndex + 1;
					oTreeNodeParent.Tag = saDataSetCols;

					nRowIndex++;
					bResult = true;
				}
				//---------------------------------------------------------------------------------------------------
				//Tree Root Child 생성
				//---------------------------------------------------------------------------------------------------
				else
				{
					//---------------------------------------------------------------------------------------------------
					//현재 노드의 키와 등록할 노드의 부모 키 비교(현재 등록되는 노드는 tnNode 가 부모가 되므로...)
					//---------------------------------------------------------------------------------------------------
					if (oTreeNodeParent != null && oTreeNodeParent.Name == saDataSetCols[1])
					{
						//---------------------------------------------------------------------------------------------------
						//tnNode를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						tnCurTreeNode = oTreeNodeParent.Nodes.Add(saDataSetCols[0], string.Format("{0}({1})", saDataSetCols[5], saDataSetCols[3]));
						tnCurTreeNode.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(saDataSetCols[6]));
						tnCurTreeNode.SelectedImageIndex = tnCurTreeNode.ImageIndex + 1;
						tnCurTreeNode.Tag = saDataSetCols;

						nRowIndex++;
						bResult = true;
						//---------------------------------------------------------------------------------------------------
					}
					//---------------------------------------------------------------------------------------------------
					//현재 노드의 키와 등록할 노드의 부모 키 비교(현재 등록되는 노드는 tnNode 가 부모가 아니므로...)
					//---------------------------------------------------------------------------------------------------
					else
					{
						//---------------------------------------------------------------------------------------------------
						//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 해서 자식 등록
						//---------------------------------------------------------------------------------------------------
						if (oTreeNodeParent != null && oTreeNodeParent.Nodes.ContainsKey(saDataSetCols[1]) == true)
						{
							tnCurTreeNode = oTreeNodeParent.Nodes[saDataSetCols[1]].Nodes.Add(saDataSetCols[0], string.Format("{0}({1})", saDataSetCols[5], saDataSetCols[3]));
							tnCurTreeNode.ImageIndex = this.pf_TreeImageCID(Convert.ToInt32(saDataSetCols[6]));
							tnCurTreeNode.SelectedImageIndex = tnCurTreeNode.ImageIndex + 1;
							tnCurTreeNode.Tag = saDataSetCols;

							nRowIndex++;
							oTreeNodeParent = oTreeNodeParent.Nodes[saDataSetCols[1]];
							bResult = true;
							//---------------------------------------------------------------------------------------------------
						}
						else
						{
							//---------------------------------------------------------------------------------------------------
							//트리노드가 확장된경우 현재 노드 ID가 루트인 경우 이미 트리에 있으므로 스킵 시킴
							//---------------------------------------------------------------------------------------------------
							if (oTreeNodeParent != null && saDataSetCols[0] == sTreeNodeRootID)
							{
								nRowIndex++;
								bResult = true;
							}
							else
							{
								//---------------------------------------------------------------------------------------------------
								//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 찾지못한 경우 상위 부모를 전달해서 등록
								//---------------------------------------------------------------------------------------------------
								if (oTreeNodeParent != null && oTreeNodeParent.Parent != null)
								{
									oTreeNodeParent = oTreeNodeParent.Parent;
									bResult = true;
								}
							}
							//---------------------------------------------------------------------------------------------------
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>Tree 객체에 재귀적으로 노드 구성(스택 오버플로우 발생 가능)</summary>
		/// <param name="oTreeView">트리 객체</param>
		/// <param name="oTreeNode">부모 노드 객체</param>
		/// <param name="sKey">부모 노드 키값</param>
		/// <param name="saDataSetRows">전체 노드정보 배열</param>
		/// <param name="nRowIndex">다음 노드 행</param>
		/// <param name="nOpenDepth">화면에 오픈할 노드 깊이</param>
		/// <param name="bTreeClearOK">트리 생성하기 전에 지우는 여부</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_TreeAddNode(TreeView oTreeView, TreeNode oTreeNode, string sKey, string[] saDataSetRows, int nRowIndex, int nOpenDepth, bool bTreeClearOK)
		{
			TreeNode tnCurNode = null;
			string[] saDataSetCols = null;
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };

			try
			{
				//---------------------------------------------------------------------------------------------------
				//행 범위 확인
				//---------------------------------------------------------------------------------------------------
				if (nRowIndex < saDataSetRows.Length)
				{
					//---------------------------------------------------------------------------------------------------
					//한 행의 모든 컬럼 분리(OBJECTID, PAR_OBJECTID, GRP_OBJECTID, CODE, PATTERN, KNAME)
					//---------------------------------------------------------------------------------------------------
					saDataSetCols = saDataSetRows[nRowIndex].Split(saColSepa, StringSplitOptions.None);
					//---------------------------------------------------------------------------------------------------
					//Tree Root 생성
					//---------------------------------------------------------------------------------------------------
					if (nRowIndex == 0)
					{
						if (bTreeClearOK == true)
						{
							oTreeView.Nodes.Clear();
						}
					}

					if (saDataSetCols[1] == "-1")
					{
						oTreeNode = oTreeView.Nodes.Add(saDataSetCols[0], saDataSetCols[5]);
						oTreeNode.ImageIndex = this.pf_TreeImageIndex(oTreeNode.Level);
						oTreeNode.SelectedImageIndex = oTreeNode.ImageIndex + 1;
						oTreeNode.Tag = saDataSetCols[3] + ComCls.cConst.PC_TREE_SEPARATOR_TAG + saDataSetCols[4];

						nRowIndex++;

						this.pf_TreeAddNode(oTreeView, oTreeNode, saDataSetCols[0], saDataSetRows, nRowIndex, nOpenDepth, bTreeClearOK);
					}
					//---------------------------------------------------------------------------------------------------
					//Tree Root Child 생성
					//---------------------------------------------------------------------------------------------------
					else
					{
						//---------------------------------------------------------------------------------------------------
						//현재 노드의 키와 등록할 노드의 부모 키 비교(현재 등록되는 노드는 tnNode 가 부모가 되므로...)
						//---------------------------------------------------------------------------------------------------
						if (sKey == saDataSetCols[1])
						{
							//---------------------------------------------------------------------------------------------------
							//tnNode를 부모로 해서 자식 등록
							//---------------------------------------------------------------------------------------------------
							tnCurNode = oTreeNode.Nodes.Add(saDataSetCols[0], saDataSetCols[5]);// + "-" + tnNode.Name + "," + saDataSetCols[0]);
							tnCurNode.ImageIndex = this.pf_TreeImageIndex(tnCurNode.Level);
							tnCurNode.SelectedImageIndex = tnCurNode.ImageIndex + 1;
							tnCurNode.Tag = saDataSetCols[3] + ComCls.cConst.PC_TREE_SEPARATOR_TAG + saDataSetCols[4];

							nRowIndex++;
							//tnNode.ExpandAll();
							//Application.DoEvents();
							//---------------------------------------------------------------------------------------------------
							//tnNode를 부모로 해서 자식 등록
							//---------------------------------------------------------------------------------------------------
							if (nRowIndex < saDataSetRows.Length)
							{
								//this.pf_TreeAddNode(oTreeView, tnNode, saDataSetCols[1], saDataSetRows, nRow, nOpenDepth, bTreeClearOK);
								this.pf_TreeAddNode(oTreeView, oTreeNode, oTreeNode.Name, saDataSetRows, nRowIndex, nOpenDepth, bTreeClearOK);
							}
							//---------------------------------------------------------------------------------------------------
						}
						//---------------------------------------------------------------------------------------------------
						//현재 노드의 키와 등록할 노드의 부모 키 비교(현재 등록되는 노드는 tnNode 가 부모가 아니므로...)
						//---------------------------------------------------------------------------------------------------
						else
						{
							//---------------------------------------------------------------------------------------------------
							//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 해서 자식 등록
							//---------------------------------------------------------------------------------------------------
							if (oTreeNode.Nodes.ContainsKey(saDataSetCols[1]) == true)
							{
								tnCurNode = oTreeNode.Nodes[saDataSetCols[1]].Nodes.Add(saDataSetCols[0], saDataSetCols[5]);// + "-" + saDataSetCols[1] + "," + saDataSetCols[0]);
								tnCurNode.ImageIndex = this.pf_TreeImageIndex(tnCurNode.Level);
								tnCurNode.SelectedImageIndex = tnCurNode.ImageIndex + 1;
								tnCurNode.Tag = saDataSetCols[3] + ComCls.cConst.PC_TREE_SEPARATOR_TAG + saDataSetCols[4];

								nRowIndex++;
								//tnNode.ExpandAll();
								//Application.DoEvents();
								//---------------------------------------------------------------------------------------------------
								//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 해서 자식 등록
								//---------------------------------------------------------------------------------------------------
								if (nRowIndex < saDataSetRows.Length)
								{
									//this.pf_TreeAddNode(oTreeView, tnNode.Nodes[saDataSetCols[1]], saDataSetCols[1], saDataSetRows, nRow, nOpenDepth, bTreeClearOK);
									this.pf_TreeAddNode(oTreeView, oTreeNode.Nodes[saDataSetCols[1]], oTreeNode.Nodes[saDataSetCols[1]].Name, saDataSetRows, nRowIndex, nOpenDepth, bTreeClearOK);
								}
								//---------------------------------------------------------------------------------------------------
							}
							else
							{
								//---------------------------------------------------------------------------------------------------
								//tnNode.Nodes[sArrDataSetCols[1]]를 부모로 찾지못한 경우 상위 부모를 전달해서 등록
								//---------------------------------------------------------------------------------------------------
								this.pf_TreeAddNode(oTreeView, oTreeNode.Parent, oTreeNode.Parent.Name, saDataSetRows, nRowIndex, nOpenDepth, bTreeClearOK);
								//---------------------------------------------------------------------------------------------------
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			finally
			{
				if (oTreeNode.Level < nOpenDepth - 1)
				{
					oTreeNode.Expand();
				}
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>Tree List View 아이템의 서브 아이템 구성</summary>
		/// <param name="oTreeListViewItem">트리 리스트 아이템 객체</param>
		/// <param name="saDataSubItemsKey">트리 리스트 아이템의 서브아이템의 Key 배열 정보</param>
		/// <param name="saDataSubItemsText">트리 리스트 아이템의 서브아이템의 Text 배열 정보</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeAddSubItems(ref TreeListViewItem oTreeListViewItem, string[] saDataSubItemsKey, string[] saDataSubItemsText)
		{
			bool bResult = false;
			ListViewItem.ListViewSubItem oItem = null;

			try
			{
				if (oTreeListViewItem != null && saDataSubItemsKey != null && saDataSubItemsText != null)
				{
					for (int nIndex = 0; nIndex < saDataSubItemsKey.Length; nIndex++)
					{
						oItem = oTreeListViewItem.SubItems.Add(saDataSubItemsText[nIndex]);

						oItem.Name = saDataSubItemsKey[nIndex];
					}

					bResult = true;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드를 이동 또는 복사하는 경우 가능한지 Class ID를 확인</summary>
		/// <param name="oTreeNodeSource">트리뷰에서 소스 노드 객체 핸들</param>
		/// <param name="oTreeNodeTarget">트리뷰에서 목적 노드 객체 핸들</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeCheckNodeCID(TreeNode oTreeNodeSource, TreeNode oTreeNodeTarget)
		{
			bool bResult = false;
			string[] saTreeNodeSourceInfo = null;
			string[] saTreeNodeTargetInfo = null;
			int nSourceCID = 0;
			int nTargetCID = 0;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//노드를 이동 또는 복사 가능한지 확인
				//---------------------------------------------------------------------------------------------------
				saTreeNodeSourceInfo = (string[])oTreeNodeSource.Tag;
				saTreeNodeTargetInfo = (string[])oTreeNodeTarget.Tag;

				if (saTreeNodeSourceInfo != null && saTreeNodeTargetInfo != null)
				{
					nSourceCID = Convert.ToInt32(saTreeNodeSourceInfo[6]);
					nTargetCID = Convert.ToInt32(saTreeNodeTargetInfo[6]);

					switch (nSourceCID)
					{
						case 1300: bResult = false; break;							//Projects
						case 1310: if (nTargetCID == 1310) bResult = true; break;	//Project Group
						case 1320: if (nTargetCID == 1310) bResult = true; break;	//Project
						case 1330: if (nTargetCID == 1320) bResult = true; break;	//Product

						case 1100:
						case 1110: if (nTargetCID == 1330 || nTargetCID == 1100 || nTargetCID == 1110)
								bResult = true; break;							//Product, Items, Part
						default: bResult = false; break;							//etc
					}
				}
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드를 이동 또는 복사하는 경우 소스가 타겟의 부모들중 하나인지 재귀로 확인</summary>
		/// <param name="oTreeNodeSource">트리뷰에서 소스 노드 객체 핸들</param>
		/// <param name="oTreeNodeTarget">트리뷰에서 목적 노드 객체 핸들</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeContainsNode(TreeNode oTreeNodeSource, TreeNode oTreeNodeTarget)
		{
			try
			{
				//---------------------------------------------------------------------------------------------------
				//소스가 타겟의 부모들중 하나인지 재귀로 확인
				//---------------------------------------------------------------------------------------------------
				if (oTreeNodeTarget.Parent == null) return false;
				if (oTreeNodeTarget.Parent.Equals(oTreeNodeSource)) return true;

				return pf_TreeContainsNode(oTreeNodeSource, oTreeNodeTarget.Parent);

				//---------------------------------------------------------------------------------------------------
				//또는
				//---------------------------------------------------------------------------------------------------
				//bool bResult = false;
				//if (oTreeNodeDragSource.Nodes.Find(oTreeNodeDropTarget.Name, true).Length > 0) bResult = true;
				//return bResult;
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 노드별 Class ID에 따른 이미지 번호를 구한다</summary>
		/// <param name="nCID">트리뷰 노드의 Class ID</param>
		/// <returns>int</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public int pf_TreeImageCID(int nCID)
		{
			int nResult = 0;

			try
			{
				switch (nCID)
				{
					case 1300: nResult = 0; break;	//Projects
					case 1310: nResult = 2; break;	//Project Group
					case 1320: nResult = 4; break;	//Project
					case 1330: nResult = 6; break;	//Product
					case 1100:
					case 1110: nResult = 8; break;	//Items, Part
					default: nResult = 8; break;	//etc
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return nResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 노드별 레벨에 따른 이미지 번호를 구한다</summary>
		/// <param name="nLevel">트리뷰 노드 레벨</param>
		/// <returns>int</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public int pf_TreeImageIndex(int nLevel)
		{
			int nResult = 0;

			try
			{
				switch (nLevel)
				{
					case 0:
					case 1:
					case 2:
					case 3:
					case 4:
					case 5:
					case 6:
						nResult = nLevel * 2;
						break;
					default:
						nResult = 12;
						break;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return nResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 초기화 및 노드 확장시 DB 읽는 방법 지정</summary>
		/// <param name="oTreeView">트리뷰 객체 핸들</param>
		/// <param name="delTreeView_BeforeExpand_FunctionName">트리뷰에서 노드가 확장될때 실행할 함수 포인터</param>
		/// <param name="oImageList">트리뷰 노드에 표시할 이미지가 들어있는 이미지 리스트 객체 핸들</param>
		/// <param name="bTreeNodeExpandAlwaysDbReadOK">트리뷰 노드를 확장할 때 항상 DB에서 읽는지 여부</param>
		/// <param name="bTreeNodeSelectMouseRightButtonOK">트리뷰 노드를 마우스 오른쪽 버튼으로 클릭하도록 허용 여부</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeInit(TreeView oTreeView, pv_TreeView_delBeforeExpand delTreeView_BeforeExpand_FunctionName, ImageList oImageList, bool bTreeNodeExpandAlwaysDbReadOK, MouseButtons eTreeNodeSelectButton)
		{
			bool bResult = true;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//트리뷰 초기화
				//---------------------------------------------------------------------------------------------------
				oTreeView.HideSelection = false;
				//oTreeView.HotTracking = true;
				oTreeView.ShowNodeToolTips = true;
				//---------------------------------------------------------------------------------------------------
				//트리뷰 이미지 리스트 연결
				//---------------------------------------------------------------------------------------------------
				if (oImageList != null)
				{
					oTreeView.ImageList = oImageList;
				}
				//---------------------------------------------------------------------------------------------------
				//트리뷰 노드 확장할 때 실행할 함수 포인터 연결 및 이벤트 핸들러 생성
				//---------------------------------------------------------------------------------------------------
				if (delTreeView_BeforeExpand_FunctionName != null)
				{
					this.pv_TreeView_delBeforeExpand_FunctionName = delTreeView_BeforeExpand_FunctionName;
					oTreeView.BeforeExpand -= new TreeViewCancelEventHandler(pf_TreeInit_oTreeView_BeforeExpand);
					oTreeView.BeforeExpand += new TreeViewCancelEventHandler(pf_TreeInit_oTreeView_BeforeExpand);
				}

				if (eTreeNodeSelectButton == MouseButtons.Right)
				{
					oTreeView.NodeMouseClick += new TreeNodeMouseClickEventHandler(pf_TreeInit_oTreeView_NodeMouseClick);
				}
				//---------------------------------------------------------------------------------------------------
				//트리뷰 노드 확장할 때 항상 DB 읽을지 여부
				//---------------------------------------------------------------------------------------------------
				this.pv_TreeView_bTreeNodeExpandAlwaysDbReadOK = bTreeNodeExpandAlwaysDbReadOK;
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 컨텍스트 메뉴 초기화</summary>
		/// <param name="oTreeView">트리뷰 객체 핸들</param>
		/// <param name="saContextMenu">트리뷰 컨텍스트 메뉴 타이틀 배열</param>
		/// <param name="delTreeView_ContextMenuClick_FunctionName">트리뷰 컨텍스트 메뉴에서 클릭될때 실행할 함수 포인터</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeInit_ContextMenu(TreeView oTreeView, string[] saContextMenu, pv_TreeView_delContextMenuClick delTreeView_ContextMenuClick_FunctionName)
		{
			bool bResult = true;
			MenuItem oMenuItem = null;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//트리뷰에 컨텍스트 메뉴 초기화
				//---------------------------------------------------------------------------------------------------
				if (saContextMenu != null && delTreeView_ContextMenuClick_FunctionName != null)
				{
					if (this.pv_TreeView_cmTreeView == null)
					{
						this.pv_TreeView_cmTreeView = new ContextMenu();
					}
					else
					{
						this.pv_TreeView_cmTreeView.MenuItems.Clear();
					}

					for (int nNum = 0; nNum < saContextMenu.Length; nNum++)
					{
						if (saContextMenu[nNum].Replace(" ", "") != "")
						{
							//컨텍스트 메뉴 아이템 등록
							oMenuItem = this.pv_TreeView_cmTreeView.MenuItems.Add(saContextMenu[nNum]);
							//컨텍스트 메뉴 아이템 키 지정
							oMenuItem.Name = saContextMenu[nNum];
							//컨텍스트 메뉴 아이템 이벤트 핸들러 생성
							oMenuItem.Click += new EventHandler(pf_TreeInit_ContextMenu_Click);
						}
					}

					if (this.pv_TreeView_cmTreeView.MenuItems.Count > 0)
					{
						//트리뷰에 컨텍스트 메뉴 등록
						oTreeView.ContextMenu = this.pv_TreeView_cmTreeView;

						//트리뷰 컨텍스트 메뉴 선택할 때 실행할 함수 포인터 연결
						this.pv_TreeView_delContextMenuClick_FunctionName = delTreeView_ContextMenuClick_FunctionName;
					}
				}
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 컨텍스트 메뉴를 클릭하면 호출</summary>
		/// <param name="sender">트리뷰 컨텍스트 메뉴 아이템 객체 핸들</param>
		/// <param name="e">트리뷰 컨텍스트 메뉴에서 클릭되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_ContextMenu_Click(object sender, EventArgs e)
		{
			try
			{
				//---------------------------------------------------------------------------------------------------
				//트리뷰 컨텍스트 메뉴 클릭하면 델리게이트를 통해 실행
				//---------------------------------------------------------------------------------------------------
				this.pv_TreeView_delContextMenuClick_FunctionName(this.pv_TreeView_cmTreeView.SourceControl as TreeView, this.pv_TreeView_cmTreeView, sender as MenuItem, this.pv_TreeView_cmTreeView.MenuItems.IndexOf(sender as MenuItem));
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 드래그 드롭 초기화</summary>
		/// <param name="oTreeView">트리뷰 객체 핸들</param>
		/// <param name="delTreeView_DragDrop">트리뷰에서 노드가 드롭될때 실행할 함수 포인터</param>
		/// <param name="nTreeNodeDragDropLevel">트리뷰 노드를 드래그 드롭할 때 드래그 드롭이 가능한 레벨</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeInit_DragDrop(TreeView oTreeView, pv_TreeView_delDragDrop delTreeView_DragDrop_FunctionName, int nTreeNodeDragDropLevel)
		{
			bool bResult = true;

			try
			{
				if (delTreeView_DragDrop_FunctionName != null)
				{
					//---------------------------------------------------------------------------------------------------
					//트리뷰 드래그 드롭 초기화
					//---------------------------------------------------------------------------------------------------
					oTreeView.AllowDrop = true;
					//---------------------------------------------------------------------------------------------------
					//트리뷰에서 이벤트 핸들러를 연결할 함수 포인터 저장
					//---------------------------------------------------------------------------------------------------
					this.pv_TreeView_delDragDrop_FunctionName = delTreeView_DragDrop_FunctionName;
					//---------------------------------------------------------------------------------------------------
					//트리뷰 이벤트 핸들러 제거(pf_TreeInit() 함수 반복 호출을 가능하도록)
					//---------------------------------------------------------------------------------------------------
					oTreeView.DragDrop -= new DragEventHandler(pf_TreeInit_oTreeView_DragDrop);
					oTreeView.DragEnter -= new DragEventHandler(pf_TreeInit_oTreeView_DragEnter);
					oTreeView.DragOver -= new DragEventHandler(pf_TreeInit_oTreeView_DragOver);
					oTreeView.ItemDrag -= new ItemDragEventHandler(pf_TreeInit_oTreeView_ItemDrag);
					//---------------------------------------------------------------------------------------------------
					//트리뷰 이벤트 핸들러 등록
					//---------------------------------------------------------------------------------------------------
					oTreeView.DragDrop += new DragEventHandler(pf_TreeInit_oTreeView_DragDrop);
					oTreeView.DragEnter += new DragEventHandler(pf_TreeInit_oTreeView_DragEnter);
					oTreeView.DragOver += new DragEventHandler(pf_TreeInit_oTreeView_DragOver);
					oTreeView.ItemDrag += new ItemDragEventHandler(pf_TreeInit_oTreeView_ItemDrag);
					//---------------------------------------------------------------------------------------------------
					//트리뷰 드래그 드롭 가능한 레벨 저장
					//---------------------------------------------------------------------------------------------------
					this.pv_TreeView_nTreeNodeDragDropLevel = nTreeNodeDragDropLevel;
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드가 확장되면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">트리뷰 객체 핸들</param>
		/// <param name="e">트리뷰에서 노드가 확장되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_oTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
		{
			try
			{
				//---------------------------------------------------------------------------------------------------
				//트리뷰 특정 노드의 하위 노드 읽기
				//---------------------------------------------------------------------------------------------------
				if (this.pv_TreeView_delBeforeExpand_FunctionName != null)
				{
					this.pv_TreeView_delBeforeExpand_FunctionName(sender as TreeView, e, e.Node, this.pv_TreeView_bTreeNodeExpandAlwaysDbReadOK);
				}
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드가 다른 노드에 드롭되면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">트리뷰 객체 핸들</param>
		/// <param name="e">트리뷰에서 노드가 다른 노드에 드롭되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_oTreeView_DragDrop(object sender, DragEventArgs e)
		{
			Point pPos;
			TreeNode oTreeNodeDragSource = null;
			TreeNode oTreeNodeDropTarget = null;
			bool bOldTreeNodeExpandAlwaysDbReadOK = this.pv_TreeView_bTreeNodeExpandAlwaysDbReadOK;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//트리뷰 소스 노드 구하기
				//---------------------------------------------------------------------------------------------------
				oTreeNodeDragSource = e.Data.GetData(typeof(TreeNode)) as TreeNode;
				//---------------------------------------------------------------------------------------------------
				//마우스 드래그 드롭 위치로 타겟 노드 찾기
				//---------------------------------------------------------------------------------------------------
				pPos = (sender as TreeView).PointToClient(new Point(e.X, e.Y));
				oTreeNodeDropTarget = (sender as TreeView).GetNodeAt(pPos);
				//---------------------------------------------------------------------------------------------------

				if (oTreeNodeDropTarget != null && oTreeNodeDragSource != null)
				{
					//드래그 시작 노드를 선택 노드로
					(sender as TreeView).SelectedNode = oTreeNodeDragSource;

					//소스와 타겟이 같은지 판단
					if (oTreeNodeDropTarget.Name != oTreeNodeDragSource.Name)
					{
						//소스가 타겟의 모든 부모들중 하나인지 확인(아래로 이동인 경우 필요)
						if (this.pf_TreeContainsNode(oTreeNodeDragSource, oTreeNodeDropTarget) == false)
						{
							//---------------------------------------------------------------------------------------------------
							//트리 노드 이동인 경우
							//---------------------------------------------------------------------------------------------------
							if (e.Effect == DragDropEffects.Move)
							{
								//소스가 타겟의 바로아래 자식인지 확인(위로 이동인 경우 필요 - MOVE 일때 한부모 밑에 같은 자식은 한개로 가정)
								if (oTreeNodeDropTarget.Nodes.ContainsKey(oTreeNodeDragSource.Name) == false)
								{
									if (this.pv_TreeView_delDragDrop_FunctionName != null)
									{
										//---------------------------------------------------------------------------------------------------
										//트리뷰 노드 드래그 드롭시 데이터베이스에 반영하고 다시 읽어서 트리뷰에 반영
										//---------------------------------------------------------------------------------------------------
										if (this.pv_TreeView_delDragDrop_FunctionName(sender as TreeView, e, oTreeNodeDragSource, oTreeNodeDropTarget) == true)
										{
											//드래그 시작 노드를 트리뷰에서 제거
											oTreeNodeDragSource.Remove();

											//이동한 노드의 부모 노드를 강제로 읽어서 복사한 자식노드들을 화면에 표시
											this.pv_TreeView_delBeforeExpand_FunctionName(sender as TreeView, new TreeViewCancelEventArgs(oTreeNodeDropTarget, false, TreeViewAction.Expand), oTreeNodeDropTarget, true);
											oTreeNodeDropTarget.Expand();

											//드래그 이동 노드를 선택 노드로
											(sender as TreeView).SelectedNode = oTreeNodeDragSource;
										}
										//---------------------------------------------------------------------------------------------------
									}
								}
							}
							//---------------------------------------------------------------------------------------------------
							//트리 노드 복사인 경우
							//---------------------------------------------------------------------------------------------------
							else if (e.Effect == DragDropEffects.Copy)
							{
								if (this.pv_TreeView_delDragDrop_FunctionName != null)
								{
									//---------------------------------------------------------------------------------------------------
									//트리뷰 노드 드래그 드롭시 데이터베이스에 반영하고 다시 읽어서 트리뷰에 반영
									//---------------------------------------------------------------------------------------------------
									if (this.pv_TreeView_delDragDrop_FunctionName(sender as TreeView, e, oTreeNodeDragSource, oTreeNodeDropTarget) == true)
									{
										//복사한 노드의 부모 노드를 강제로 읽어서 복사한 자식노드들을 화면에 표시
										this.pv_TreeView_delBeforeExpand_FunctionName(sender as TreeView, new TreeViewCancelEventArgs(oTreeNodeDropTarget, false, TreeViewAction.Expand), oTreeNodeDropTarget, true);
										oTreeNodeDropTarget.Expand();

										//드래그 복사 노드를 선택 노드로
										(sender as TreeView).SelectedNode = oTreeNodeDropTarget;
									}
									//---------------------------------------------------------------------------------------------------
								}
							}

							////---------------------------------------------------------------------------------------------------
							////트리뷰 노드 드래그 드롭시 노드를 먼저 확장하면 자식노드를 읽지않은 경우 DB를 읽어온다
							////---------------------------------------------------------------------------------------------------
							//oTreeNodeDropTarget.Expand();
							////---------------------------------------------------------------------------------------------------
							////트리 노드 이동
							////---------------------------------------------------------------------------------------------------
							//if (e.Effect == DragDropEffects.Move)
							//{
							//    //드래그 시작 노드를 트리뷰에서 제거
							//    oTreeNodeDragSource.Remove();

							//    //드래그 시작 노드의 모든 자식노드 까지 드롭 위치의 노드에 추가
							//    oTreeNodeDropTarget.Nodes.Add(oTreeNodeDragSource);
							//    oTreeNodeDropTarget.Expand();

							//    //드래그 이동 노드를 선택 노드로
							//    (sender as TreeView).SelectedNode = oTreeNodeDragSource;
							//}
							////---------------------------------------------------------------------------------------------------
							////트리 노드 복사
							////---------------------------------------------------------------------------------------------------
							//else if (e.Effect == DragDropEffects.Copy)
							//{
							//    //드래그 시작 노드의 모든 자식노드 까지 복사본 만들기
							//    oTreeNodeDragSourceCopy = (TreeNode)oTreeNodeDragSource.Clone();

							//    //드래그 시작 노드의 모든 자식노드 까지 드롭 위치의 노드에 추가
							//    oTreeNodeDropTarget.Nodes.Add(oTreeNodeDragSourceCopy);
							//    oTreeNodeDropTarget.Expand();

							//    //드래그 복사 노드를 선택 노드로
							//    (sender as TreeView).SelectedNode = oTreeNodeDragSourceCopy;
							//}
							////---------------------------------------------------------------------------------------------------
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				if ((sender as TreeView).Nodes.Count > 0)
				{
					//---------------------------------------------------------------------------------------------------
					//소스 노드 모양 원래대로(복사인 경우 남아 있으므로 필요)
					//---------------------------------------------------------------------------------------------------
					if (oTreeNodeDragSource != null)
					{
						//소스 노드의 배경 색상을 원래대로 복원
						oTreeNodeDragSource.BackColor = this.mv_TreeNodeDefaultBackColor;
					}
					//---------------------------------------------------------------------------------------------------
					//타겟 노드 모양 원래대로(이동인 경우 필요)
					//---------------------------------------------------------------------------------------------------
					if ((sender as TreeView).SelectedNode == null)
					{
						(sender as TreeView).SelectedNode = (sender as TreeView).Nodes[0];
					}

					//타겟 노드의 배경 색상을 원래대로 복원
					(sender as TreeView).SelectedNode.BackColor = this.mv_TreeNodeDefaultBackColor;
					//---------------------------------------------------------------------------------------------------
				}
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드가 드래그 시작되면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">트리뷰 객체 핸들</param>
		/// <param name="e">트리뷰에서 노드가 드래그 시작되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_oTreeView_DragEnter(object sender, DragEventArgs e)
		{
			try
			{
				//---------------------------------------------------------------------------------------------------
				//드래그 동작 모두 적용
				//---------------------------------------------------------------------------------------------------
				e.Effect = e.AllowedEffect;
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드가 다른 노드위로 오버되면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">트리뷰 객체 핸들</param>
		/// <param name="e">트리뷰에서 노드가 다른 노드위로 오버되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_oTreeView_DragOver(object sender, DragEventArgs e)
		{
			Point pPos;
			TreeNode oTreeNodeDropSource = null;
			TreeNode oTreeNodeDropTarget = null;
			bool bJobOK = true;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//트리뷰 소스 노드 구하기
				//---------------------------------------------------------------------------------------------------
				//oTreeNodeDropSource = (sender as TreeView).SelectedNode;
				oTreeNodeDropSource = e.Data.GetData(typeof(TreeNode)) as TreeNode;
				//---------------------------------------------------------------------------------------------------
				//마우스 드래그 위치의 소스/타겟 노드 찾기
				//---------------------------------------------------------------------------------------------------
				pPos = (sender as TreeView).PointToClient(new Point(e.X, e.Y));
				oTreeNodeDropTarget = (sender as TreeView).GetNodeAt(pPos);
				//---------------------------------------------------------------------------------------------------
				if (oTreeNodeDropSource != null && oTreeNodeDropTarget != null)
				{
					if (oTreeNodeDropTarget.Level >= this.pv_TreeView_nTreeNodeDragDropLevel - 1)
					{
						//---------------------------------------------------------------------------------------------------
						//트리뷰 노드의 Class ID를 확인해서 복사 또는 이동이 가능한지 여부 파악
						//---------------------------------------------------------------------------------------------------
						if (this.pf_TreeCheckNodeCID(oTreeNodeDropSource, oTreeNodeDropTarget) == true)
						{
							//---------------------------------------------------------------------------------------------------
							//작업 모드 설정
							//---------------------------------------------------------------------------------------------------
							if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
							{
								e.Effect = DragDropEffects.Copy;
							}
							else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
							{
								e.Effect = DragDropEffects.Move;
							}
							//---------------------------------------------------------------------------------------------------
						}
						else bJobOK = false;
						//---------------------------------------------------------------------------------------------------
					}
					else bJobOK = false;

					//---------------------------------------------------------------------------------------------------
					//타겟 노드 선택
					//---------------------------------------------------------------------------------------------------
					(sender as TreeView).SelectedNode = oTreeNodeDropTarget;
					//---------------------------------------------------------------------------------------------------
				}
				else bJobOK = false;

				if (oTreeNodeDropSource != null)
				{
					if (bJobOK == true)
					{
						//이동 또는 복사할 소스 노드의 배경색상을 선택 색상으로 지정
						oTreeNodeDropSource.BackColor = this.mv_TreeNodeSelectBackColor;
					}
					else
					{
						//드래그 드롭 작업 없음(노드
						e.Effect = DragDropEffects.None;

						//이동 또는 복사할 소스 노드의 배경색상 원래대로 복원
						oTreeNodeDropSource.BackColor = this.mv_TreeNodeDefaultBackColor;
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드가 드래그 시작되면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">트리뷰 객체 핸들</param>
		/// <param name="e">트리뷰에서 노드가 드래그 시작되면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_oTreeView_ItemDrag(object sender, ItemDragEventArgs e)
		{
			try
			{
				if (this.pv_TreeView_nTreeNodeDragDropLevel != -1)
				{
					if (e.Button == System.Windows.Forms.MouseButtons.Left && (e.Item as TreeNode).Level >= this.pv_TreeView_nTreeNodeDragDropLevel - 1)
					{
						//---------------------------------------------------------------------------------------------------
						//드래그 시작
						//---------------------------------------------------------------------------------------------------
						//노드의 기본 배경색상 저장
						this.mv_TreeNodeDefaultBackColor = (e.Item as TreeNode).BackColor;

						//노드의 기본 배경색상을 선택 색상으로 지정
						(e.Item as TreeNode).BackColor = this.mv_TreeNodeSelectBackColor;

						(sender as TreeView).DoDragDrop(e.Item, DragDropEffects.All);
						//---------------------------------------------------------------------------------------------------
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰에서 노드를 마우스로 클릭하면 호출되는 이벤트 핸들러</summary>
		/// <param name="sender">트리뷰 객체 핸들</param>
		/// <param name="e">트리뷰에서 노드를 마우스로 클릭하면 전달되는 인자</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		private void pf_TreeInit_oTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			try
			{
				//if (e.Button == MouseButtons.Right)
				{
					(sender as TreeView).SelectedNode = e.Node;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리 리스트 뷰의 아이템에서 Name으로 특정 아이템을 찾기</summary>
		/// <param name="oTreeListViewItem">트리 리스트 뷰의 아이템</param>
		/// <param name="sTreeItemName">찾을 아이템 Name</param>
		/// <param name="nFindIndex">찾은 위치 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_TreeItemContains(TreeListViewItem oTreeListViewItem, string sTreeItemName, ref int nFindIndex)
		{
			bool bResult = false;

			try
			{
				nFindIndex = -1;

				if (oTreeListViewItem != null)
				{
					for (int nIndex = 0; nIndex < oTreeListViewItem.Items.Count; nIndex++)
					{
						if (oTreeListViewItem.Items[nIndex].Name == sTreeItemName)
						{
							bResult = true;
							nFindIndex = nIndex;
							break;
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>모든 BOM 어플리케이션(Mdi Child Form) 정렬</summary>
		/// <param name="frmMidForm">메인 부모폼 객체 핸들</param>
		/// <param name="eArrangeMethod">BOM 어플리케이션(Mdi Child Form) 정렬 방법</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WindowsAllArrange(Form frmMidForm, MdiLayout eArrangeMethod)
		{
			bool bResult = true;

			try
			{
				frmMidForm.LayoutMdi(eArrangeMethod);
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>모든 BOM 어플리케이션(Mdi Child Form) 닫기</summary>
		/// <param name="frmForm">모든 BOM 어플리케이션(Mdi Child Form) 폼 배열</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WindowsAllClose(Form[] frmForm)
		{
			bool bResult = true;

			try
			{
				if (frmForm != null && frmForm.Length > 0)
				{
					for (int nNum = 0; nNum < frmForm.Length; nNum++)
					{
						frmForm[nNum].Close();
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>모든 BOM 어플리케이션(Mdi Child Form) 윈도우 상태 지정</summary>
		/// <param name="frmForm">모든 BOM 어플리케이션(Mdi Child Form) 폼 배열</param>
		/// <param name="eFormWindowState">모든 BOM 어플리케이션(Mdi Child Form) 폼 상태</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WindowsAllStatus(Form[] frmForm, FormWindowState eFormWindowState)
		{
			bool bResult = true;

			try
			{
				if (frmForm != null && frmForm.Length > 0)
				{
					for (int nNum = 0; nNum < frmForm.Length; nNum++)
					{
						frmForm[nNum].WindowState = eFormWindowState;
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>인증 확인</summary>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpCertification()
		{
			bool bResult = false;

			try
			{
				bResult = true;
				//......
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 데이터 셋을 PARSE 형으로 생성(Mode : R)</summary>
		/// <param name="oDataSet">DataSet 객체</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpConvertDataSetToParse(DataSet oDataSet)
		{
			StringBuilder sResult = new StringBuilder();

			int nRowCount = 0;
			int nColCount = 0;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 객체 값이 있는경우
				//---------------------------------------------------------------------------------------------------
				if (oDataSet != null && oDataSet.Tables.Count > 0)
				{
					//---------------------------------------------------------------------------------------------------
					//DataSet 객체 Tables[0]의 크기 구하기
					//---------------------------------------------------------------------------------------------------
					if (oDataSet != null && oDataSet.Tables.Count > 0)
					{
						nRowCount = oDataSet.Tables[0].Rows.Count;
						nColCount = oDataSet.Tables[0].Columns.Count;
					}

					if (nRowCount > 0 && nColCount > 0)
					{
						//테이블 정보 "⊙행수,열수◆" 만들기
						sResult.Append(string.Format("{0}{1},{2}{3}", ComCls.cConst.PC_SEPARATOR_HEADER, nRowCount, nColCount, ComCls.cConst.PC_SEPARATOR_RECORD));

						//행수 만큼 반복
						for (int nRow = 0; nRow < nRowCount; nRow++)
						{
							//열수 만큼 반복
							for (int nCol = 0; nCol < nColCount; nCol++)
							{
								if (nCol == 0)
								{
									sResult.Append(oDataSet.Tables[0].Rows[nRow][nCol].ToString());
								}
								else
								{
									sResult.Append(ComCls.cConst.PC_SEPARATOR_COL + oDataSet.Tables[0].Rows[nRow][nCol].ToString());
								}
							}
							//마지막 확인해서 다음행 구분자(▼) 또는 테이블 끝 구분자(▣)를 붙이기
							if (nRow < nRowCount - 1)
							{
								sResult.Append(ComCls.cConst.PC_SEPARATOR_ROW);
							}
							else
							{
								sResult.Append(ComCls.cConst.PC_SEPARATOR_FOOTER);
							}
						}
					}
					else
					{
						//테이블에 데이터가 없으면 테이블 정보를 "⊙행수,열수◆▣" 로 만들기
						sResult.Append(string.Format("{0}{1},{2}{3}{4}", ComCls.cConst.PC_SEPARATOR_HEADER, nRowCount, nColCount, ComCls.cConst.PC_SEPARATOR_RECORD, ComCls.cConst.PC_SEPARATOR_FOOTER));
					}
				}
				else
				{
					//데이터 셋이 없으면 테이블 정보를 "⊙0,0◆▣" 로 만들기
					sResult.Append(string.Format("{0}{1},{2}{3}{4}", ComCls.cConst.PC_SEPARATOR_HEADER, 0, 0, ComCls.cConst.PC_SEPARATOR_RECORD, ComCls.cConst.PC_SEPARATOR_FOOTER));
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult.ToString();
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 데이터 셋을 PARSE 형으로 생성(Mode : CUD)</summary>
		/// <param name="nRowCount">처리 레코드 수</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpConvertDataSetToParse(long nRowCount)
		{
			StringBuilder sResult = new StringBuilder();

			try
			{
				//---------------------------------------------------------------------------------------------------
				//웹 브라우저에 출력할 내용을 "⊙행수,1◆▣" 로 만들기
				//---------------------------------------------------------------------------------------------------
				sResult.Append(string.Format("{0}{1},{2}{3}{4}", ComCls.cConst.PC_SEPARATOR_HEADER, nRowCount, 1, ComCls.cConst.PC_SEPARATOR_RECORD, ComCls.cConst.PC_SEPARATOR_FOOTER));
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult.ToString();
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 데이터 셋을 PARSE 형으로 생성(Mode : TCUD)</summary>
		/// <param name="nRowCount">처리 레코드 수</param>
		/// <param name="sSID">사용할 세션 ID</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpConvertDataSetToParse(long nRowCount, string sSID)
		{
			StringBuilder sResult = new StringBuilder();

			try
			{
				//---------------------------------------------------------------------------------------------------
				//웹 브라우저에 출력할 내용을 "⊙행수,1◆▣" 로 만들기
				//---------------------------------------------------------------------------------------------------
				sResult.Append(string.Format("{0}{1},{2}{3}{4}", ComCls.cConst.PC_SEPARATOR_HEADER, nRowCount, sSID, ComCls.cConst.PC_SEPARATOR_RECORD, ComCls.cConst.PC_SEPARATOR_FOOTER));
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult.ToString();
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 데이터 셋을 XML 형으로 생성(Mode : R)</summary>
		/// <param name="oDataSet">DataSet 객체</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpConvertDataSetToXml(DataSet oDataSet)
		{
			StringBuilder sResult = new StringBuilder();
			StringWriter swDataSet = new StringWriter();

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 객체 값이 있는경우
				//---------------------------------------------------------------------------------------------------
				if (oDataSet != null && oDataSet.Tables.Count > 0)
				{
					oDataSet.Tables[0].WriteXml(swDataSet, XmlWriteMode.WriteSchema);

					sResult.Append(ComCls.cConst.PC_SEPARATOR_HEADER + swDataSet.ToString() + ComCls.cConst.PC_SEPARATOR_FOOTER);
				}
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult.ToString();
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 데이터 셋을 XML 형으로 생성(Mode : CUD)</summary>
		/// <param name="nRowCount">처리 레코드 수</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpConvertDataSetToXml(long nRowCount)
		{
			StringBuilder sResult = new StringBuilder();

			try
			{
				//---------------------------------------------------------------------------------------------------
				//웹 브라우저에 출력할 내용을 "⊙<NewDataSet><Table><ROWCOUNT>1</ROWCOUNT></Table></NewDataSet>▣" 로 만들기
				//---------------------------------------------------------------------------------------------------
				//sResult.Append(ComCls.cConst.PC_SEPARATOR_HEADER +
				//                "<NewDataSet><Table><ROWCOUNT>" +
				//                nRowCount.ToString() +
				//                "</ROWCOUNT></Table></NewDataSet>" +
				//                ComCls.cConst.PC_SEPARATOR_FOOTER);

				sResult.Append(string.Format("{0}<NewDataSet><Table><ROWCOUNT>{1}</ROWCOUNT></Table></NewDataSet>{2}", ComCls.cConst.PC_SEPARATOR_HEADER, nRowCount, ComCls.cConst.PC_SEPARATOR_FOOTER));
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult.ToString();
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 데이터 셋을 XML 형으로 생성(Mode : TCUD)</summary>
		/// <param name="nRowCount">처리 레코드 수</param>
		/// <param name="sSID">사용할 세션 ID</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpConvertDataSetToXml(long nRowCount, string sSID)
		{
			StringBuilder sResult = new StringBuilder();

			try
			{
				//---------------------------------------------------------------------------------------------------
				//웹 브라우저에 출력할 내용을 "⊙<NewDataSet><Table><ROWCOUNT>1</ROWCOUNT></Table></NewDataSet>▣" 로 만들기
				//---------------------------------------------------------------------------------------------------
				sResult.Append(string.Format("{0}<NewDataSet><Table><ROWCOUNT>{1}</ROWCOUNT><SID>{2}</SID></Table></NewDataSet>{3}", ComCls.cConst.PC_SEPARATOR_HEADER, nRowCount, sSID, ComCls.cConst.PC_SEPARATOR_FOOTER));
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult.ToString();
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 게이트웨이를 통해 DB Sql을 실행하고 결과 반환</summary>
		/// <param name="eMode">Sql 실행 모드(CRUD)</param>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="sUrl">웹 페이지 주소 및 인자</param>
		/// <param name="sDataSet">결과 셋 문자열 전달</param>
		/// <param name="sDataSet">결과 셋 객체 전달</param>
		/// <param name="nRowCount">반환된 행수 전달</param>
		/// <param name="nColCount">반환된 열수 전달</param>
		/// <param name="sErrorMsg">에러 발생 시 에러 메시지 전달</param>
		/// <param name="sSID">트랜잭션 처리시 세션 ID 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpExecSql(ComCls.cConst.PE_WEBSQL_MODE eMode, ComCls.cConst.PE_WEBSQL_TYPE eType, string sUrl, ref string sDataSet, ref DataSet oDataSet, ref int nRowCount, ref int nColCount, ref string sErrorMsg, ref string sSID)
		{
			bool bResult = false;

			try
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.WaitCursor;

				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartSqlExec = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 DB Sql 실행
				//---------------------------------------------------------------------------------------------------
				this.mv_oWinHTTP.SetTimeouts(ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND);
				this.mv_oWinHTTP.Open("POST", sUrl, false);
				this.mv_oWinHTTP.Send();
				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecSqlExec = DateTime.Now - this.pv_Debug_dtStartSqlExec;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기
				//---------------------------------------------------------------------------------------------------
				bResult = pf_WpReadDataSet(eMode, eType, this.mv_oWinHTTP.ResponseText, ref sDataSet, ref oDataSet, ref nRowCount, ref nColCount, ref sErrorMsg, ref sSID);
				//---------------------------------------------------------------------------------------------------

				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;
			}
			catch (Exception ex)
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;

				sDataSet = null;
				nRowCount = 0;
				nColCount = 0;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 게이트웨이를 통해 DB Sql을 실행하고 결과 반환</summary>
		/// <param name="eMode">Sql 실행 모드(CRUD)</param>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="sUrl">웹 페이지 주소 및 인자</param>
		/// <param name="sDataSet">결과 셋 문자열 전달</param>
		/// <param name="sDataSet">결과 셋 객체 전달</param>
		/// <param name="nRowCount">반환된 행수 전달</param>
		/// <param name="nColCount">반환된 열수 전달</param>
		/// <param name="sErrorMsg">에러 발생 시 에러 메시지 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpExecSql(ComCls.cConst.PE_WEBSQL_MODE eMode, ComCls.cConst.PE_WEBSQL_TYPE eType, string sUrl, ref string sDataSet, ref DataSet oDataSet, ref int nRowCount, ref int nColCount, ref string sErrorMsg)
		{
			bool bResult = false;

			try
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.WaitCursor;

				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartSqlExec = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 DB Sql 실행
				//---------------------------------------------------------------------------------------------------
				this.mv_oWinHTTP.SetTimeouts(ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND);
				this.mv_oWinHTTP.Open("POST", sUrl, false);
				this.mv_oWinHTTP.Send();
				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecSqlExec = DateTime.Now - this.pv_Debug_dtStartSqlExec;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기
				//---------------------------------------------------------------------------------------------------
				bResult = pf_WpReadDataSet(eMode, eType, this.mv_oWinHTTP.ResponseText, ref sDataSet, ref oDataSet, ref nRowCount, ref nColCount, ref sErrorMsg);
				//---------------------------------------------------------------------------------------------------

				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;
			}
			catch (Exception ex)
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;

				sDataSet = null;
				nRowCount = 0;
				nColCount = 0;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 게이트웨이를 통해 DB Sql을 실행하고 결과 반환</summary>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="sUrl">웹 페이지 주소 및 인자</param>
		/// <param name="sDataSet">결과 셋 문자열 전달</param>
		/// <param name="sDataSet">결과 셋 객체 전달</param>
		/// <param name="nRowCount">반환된 행수 전달</param>
		/// <param name="nColCount">반환된 열수 전달</param>
		/// <param name="sErrorMsg">에러 발생 시 에러 메시지 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpExecSql(ComCls.cConst.PE_WEBSQL_TYPE eType, string sUrl, ref string sDataSet, ref DataSet oDataSet, ref int nRowCount, ref int nColCount, ref string sErrorMsg)
		{
			bool bResult = false;

			try
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.WaitCursor;

				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartSqlExec = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 DB Sql 실행
				//---------------------------------------------------------------------------------------------------
				this.mv_oWinHTTP.SetTimeouts(ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND);
				this.mv_oWinHTTP.Open("POST", sUrl);
				this.mv_oWinHTTP.Send();
				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecSqlExec = DateTime.Now - this.pv_Debug_dtStartSqlExec;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기
				//---------------------------------------------------------------------------------------------------
				bResult = pf_WpReadDataSet(eType, this.mv_oWinHTTP.ResponseText, ref sDataSet, ref oDataSet, ref nRowCount, ref nColCount, ref sErrorMsg);
				//---------------------------------------------------------------------------------------------------

				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;
			}
			catch (Exception ex)
			{
				this.mv_oFuncOwner.Cursor = Cursors.Default;

				sDataSet = null;
				nRowCount = 0;
				nColCount = 0;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 게이트웨이를 통해 DB Sql을 실행하고 결과 반환(Get 방식)</summary>
		/// <param name="sUrl">웹 페이지 주소 및 인자</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpExecSql(string sUrl)
		{
			string sWebDataSet = null;

			try
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.WaitCursor;

				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartSqlExec = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 DB Sql 실행
				//---------------------------------------------------------------------------------------------------
				this.mv_oWinHTTP.SetTimeouts(ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND,
											 ComCls.cConst.PC_TIMEOUT_EXECSQL_MILLISECOND);
				this.mv_oWinHTTP.Open("GET", sUrl);
				this.mv_oWinHTTP.Send();
				//---------------------------------------------------------------------------------------------------
				//DB Sql 실행 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecSqlExec = DateTime.Now - this.pv_Debug_dtStartSqlExec;
				//---------------------------------------------------------------------------------------------------
				//웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기
				//---------------------------------------------------------------------------------------------------
				sWebDataSet = pf_WpReadDataSet(this.mv_oWinHTTP.ResponseText);
				//---------------------------------------------------------------------------------------------------

				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;
			}
			catch (Exception ex)
			{
				if (this.mv_oFuncOwner != null) this.mv_oFuncOwner.Cursor = Cursors.Default;

				throw ex;
			}

			return sWebDataSet;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 페이지에서 변환된 문자들을 원래 문자로 디코딩</summary>
		/// <param name="sDataSet">웹 페이지에서 반환된 데이터 셋</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpHtmlDecodeAll(string sDataSet)
		{
			try
			{
				sDataSet = sDataSet.Replace("&quot;", Convert.ToChar(34).ToString());
				sDataSet = sDataSet.Replace("&lt;", Convert.ToChar(60).ToString());
				sDataSet = sDataSet.Replace("&gt;", Convert.ToChar(62).ToString());
				sDataSet = sDataSet.Replace("&amp;", Convert.ToChar(38).ToString());
				sDataSet = sDataSet.Replace("&nbsp;", Convert.ToChar(32).ToString());

				for (int nNum = 1; nNum < 256; nNum++)
				{
					sDataSet = sDataSet.Replace("&#" + nNum + ";", Convert.ToChar(nNum).ToString());
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sDataSet;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>메뉴 클릭 시 실행할 BOM 어플리케이션 정보 읽기</summary>
		/// <param name="saMenuTitles">메뉴 클릭 시 실행할 BOM 어플리케이션 정보배열</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpMenuReadBomApp(ref string[] saMenuTitles)
		{
			bool bResult = false;
			//---------------------------------------------------------------------------------------------------
			//Web Sql 정보 관련
			//---------------------------------------------------------------------------------------------------
			string sWebSql = null;
			string sWebArg = null;
			//---------------------------------------------------------------------------------------------------
			//DataSet 정보 관련
			//---------------------------------------------------------------------------------------------------
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };
			//---------------------------------------------------------------------------------------------------
			//Sql 실행 관련
			//---------------------------------------------------------------------------------------------------
			ComCls.cConst.PE_WEBSQL_TYPE eType = ComCls.cConst.PE_WEBSQL_TYPE.PARSE;
			string sDataSet = null;
			DataSet oDataSet = null;
			int nRowCount = 0;
			int nColCount = 0;
			string sErrorMsg = null;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//Web Sql 경로 만들기
				//---------------------------------------------------------------------------------------------------
				sWebSql = ComCls.cConst.PC_WEBSQL_WEBPARSE_URL;
				sWebArg = string.Format("?{0}={1}&{2}={3}&{4}={5}&{6}={7}",
											ComCls.cConst.PC_WEBSQL_MODE, ComCls.cConst.PC_WEBSQL_MODE_R,
											ComCls.cConst.PC_WEBSQL_TYPE, ComCls.cConst.PC_WEBSQL_TYPE_PARSE,
											ComCls.cConst.PC_WEBSQL_STYLE, ComCls.cConst.PC_WEBSQL_STYLE_SP,
											ComCls.cConst.PC_WEBSQL_CMD_SP, "SP_STANDARDCODE_MENU_R");
				sWebSql += sWebArg;

				if (this.pf_WpExecSql(eType, sWebSql, ref sDataSet, ref oDataSet, ref nRowCount, ref nColCount, ref sErrorMsg) == true)
				{
					if (nRowCount > 0 && sDataSet != null && sDataSet != "")
					{
						saMenuTitles = new string[nRowCount];

						//데이터 셋 행 분리
						saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

						if (saDataSetRows != null && saDataSetRows.Length > 0)
						{
							//Parsing 한 데이터 콤보에 추가
							for (int nRow = 0; nRow < saDataSetRows.Length; nRow++)
							{
								//데이터 행 컬럼 분리
								saDataSetCols = saDataSetRows[nRow].Split(saColSepa, StringSplitOptions.None);

								if (saDataSetCols != null && saDataSetCols.Length > 0)
								{
									saMenuTitles[nRow] = saDataSetCols[0];
								}
							}

							if (saMenuTitles != null)
							{
								bResult = true;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터셋 반환 타입에 따라 리스트뷰에 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oListView">결과 출력할 리스트뷰 객체</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="bClearOK">데이터그리드뷰에 데이터를 출력하기 전에 초기화</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpOutputDataSetToComboBox(ComCls.cConst.PE_WEBSQL_TYPE eType, ComboBox oComboBox, string sDataSet, DataSet oDataSet, bool bClearOK)
		{
			bool bResult = true;
			string[] saDataSetRows = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };

			try
			{
				//콤보 초기화
				if (bClearOK == true)
				{
					//콤보 모든 아이템 제거
					oComboBox.Items.Clear();

					//Application.DoEvents();
				}

				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행 분리
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								//Parsing 한 데이터 콤보에 추가
								for (int nRow = 0; nRow < saDataSetRows.Length; nRow++)
								{
									oComboBox.Items.Add(saDataSetRows[nRow]);
									//Application.DoEvents();
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oDataSet != null && oDataSet.Tables.Count > 0)
						{
							if (oDataSet.Tables[0].Rows.Count > 0)
							{
								//Parsing 한 데이터 콤보에 추가
								for (int nRow = 0; nRow < oDataSet.Tables[0].Rows.Count; nRow++)
								{
									oComboBox.Items.Add(oDataSet.Tables[0].Rows[nRow][0].ToString());
									//Application.DoEvents();
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
				//콤보에서 첫번째 항목이 선택되도록
				oComboBox.SelectedIndex = 0;
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터셋 반환 타입에 따라 리스트뷰에 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oListView">결과 출력할 리스트뷰 객체</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="bClearOK">데이터그리드뷰에 데이터를 출력하기 전에 초기화</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpOutputDataSetToComboBoxContainKey(ComCls.cConst.PE_WEBSQL_TYPE eType, ComboBox oComboBox, string sDataSet, DataSet oDataSet, bool bClearOK)
		{
			bool bResult = true;
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };
			string[] saComboKeyValue = null;

			try
			{
				//콤보 초기화
				if (bClearOK == true)
				{
					//콤보 모든 아이템 제거
					oComboBox.Items.Clear();

					//Application.DoEvents();
				}

				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (oComboBox != null && sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행 분리
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								saComboKeyValue = new string[saDataSetRows.Length];

								//Parsing 한 데이터 콤보에 추가
								for (int nRow = 0; nRow < saDataSetRows.Length; nRow++)
								{
									//데이터 행 컬럼 분리
									saDataSetCols = saDataSetRows[nRow].Split(saColSepa, StringSplitOptions.None);

									//첫번째는 Key, 두번째는 Text
									saComboKeyValue[nRow] = saDataSetCols[0];
									oComboBox.Items.Add(saDataSetCols[1]);
									//Application.DoEvents();
								}

								if (oComboBox.Items.Count > 0)
								{
									oComboBox.Tag = saComboKeyValue;
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oComboBox != null && oDataSet != null && oDataSet.Tables.Count > 0)
						{
							if (oDataSet.Tables[0].Rows.Count > 0)
							{
								//Parsing 한 데이터 콤보에 추가
								for (int nRow = 0; nRow < oDataSet.Tables[0].Rows.Count; nRow++)
								{
									oComboBox.Items.Add(oDataSet.Tables[0].Rows[nRow][0].ToString());
									//Application.DoEvents();
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
				//콤보에서 첫번째 항목이 선택되도록
				oComboBox.SelectedIndex = 0;
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터 셋 반환 타입에 따라 데이터그리드뷰에 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oDataGridView">결과 출력할 데이터그리드뷰 객체</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="bClearOK">데이터그리드뷰에 데이터를 출력하기 전에 초기화</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpOutputDataSetToDataGridView(ComCls.cConst.PE_WEBSQL_TYPE eType, DataGridView oDataGridView, string sDataSet, DataSet oDataSet, bool bClearOK)
		{
			bool bResult = true;
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };
			DataGridViewAutoSizeColumnsMode eDataGridViewAutoSizeColumnsMode = oDataGridView.AutoSizeColumnsMode;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartOutputDataSet = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 초기화
				//---------------------------------------------------------------------------------------------------
				//AutoSizeColumnsMode가 설정되있는 경우 속도 더럽게느림
				oDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

				if (bClearOK == true)
				{
					//데이터그리드 모든 행 제거
					oDataGridView.DataSource = null;
					oDataGridView.Rows.Clear();

					//Application.DoEvents();
				}
				//---------------------------------------------------------------------------------------------------
				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행배열 만들기
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								for (int nRow = 0; nRow < saDataSetRows.Length; nRow++)
								{
									//데이터 행 컬럼 분리
									saDataSetCols = saDataSetRows[nRow].Split(saColSepa, StringSplitOptions.None);

									//데이터그리드 컬럼수와 데이터셋 컬럼수가 동일한 경우
									if (oDataGridView.Columns.Count == saDataSetCols.Length)
									{
										//데이터그리드뷰에 결과 출력(디자인 된 컬럼 헤더가 유지됨)
										oDataGridView.Rows.Add(saDataSetCols);
									}
									else
									{
										bResult = false;
										break;
									}
								}

								//Application.DoEvents();
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oDataSet != null && oDataSet.Tables.Count > 0)
						{
							//데이터 셋 바운딩(컬럼 헤더가 자동으로 생성 됨)
							//oDataGridView.DataSource = oDataSet.Tables[0];

							for (int nRow = 0; nRow < oDataSet.Tables[0].Rows.Count; nRow++)
							{
								//데이터그리드뷰에 결과 출력(디자인 된 컬럼 헤더가 유지됨)
								oDataGridView.Rows.Add(oDataSet.Tables[0].Rows[nRow].ItemArray);
							}

							//Application.DoEvents();
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}
			finally
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecOutputDataSet = DateTime.Now - this.pv_Debug_dtStartOutputDataSet;

				//AutoSizeColumnsMode가 설정 원상복귀
				oDataGridView.AutoSizeColumnsMode = eDataGridViewAutoSizeColumnsMode;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터그리드뷰에 컬럼을 로우로 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oDataGridView">결과 출력할 데이터그리드뷰 객체</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="bClearOK">데이터그리드뷰에 데이터를 출력하기 전에 초기화</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpOutputDataSetToDataGridViewProperty(ComCls.cConst.PE_WEBSQL_TYPE eType, DataGridView oDataGridView, string sDataSet, DataSet oDataSet, bool bClearOK)
		{
			bool bResult = true;
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };
			DataGridViewAutoSizeColumnsMode eDataGridViewAutoSizeColumnsMode = oDataGridView.AutoSizeColumnsMode;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartOutputDataSet = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 초기화
				//---------------------------------------------------------------------------------------------------
				//AutoSizeColumnsMode가 설정되있는 경우 속도 더럽게느림
				oDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

				if (eType == ComCls.cConst.PE_WEBSQL_TYPE.XML && bClearOK == true)
				{
					//데이터그리드 모든 행 제거
					oDataGridView.DataSource = null;
					oDataGridView.Rows.Clear();

					//Application.DoEvents();
				}
				//---------------------------------------------------------------------------------------------------
				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우(컬럼명을 구할 수 없음)
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행배열 만들기
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								//데이터 행 컬럼 분리
								saDataSetCols = saDataSetRows[0].Split(saColSepa, StringSplitOptions.None);

								for (int nCol = 0; nCol < saDataSetCols.Length; nCol++)
								{
									oDataGridView.Rows[nCol].Cells[1].Value = saDataSetCols[nCol];
								}
							}
						}
						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우(컬럼명을 구할 수 있음)
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oDataSet != null && oDataSet.Tables.Count > 0)
						{
							if (oDataGridView.Rows.Count == 0)
							{
								for (int nCol = 0; nCol < oDataSet.Tables[0].Columns.Count; nCol++)
								{
									oDataGridView.Rows.Add(new object[] { ComCls.cConst.PE_ARGTYPE_JOBMODE.R, oDataSet.Tables[0].Columns[nCol].ColumnName.Replace("__", " "), oDataSet.Tables[0].Rows[0][nCol].ToString(), oDataSet.Tables[0].Rows[1][nCol].ToString() });
								}
							}
							else
							{
								for (int nCol = 0; nCol < oDataSet.Tables[0].Columns.Count; nCol++)
								{
									oDataGridView.Rows[nCol].Cells[0].Value = ComCls.cConst.PE_ARGTYPE_JOBMODE.R;
									oDataGridView.Rows[nCol].Cells[2].Value = oDataSet.Tables[0].Rows[0][nCol].ToString();
									oDataGridView.Rows[nCol].Cells[3].Value = oDataSet.Tables[0].Rows[1][nCol].ToString();
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}
			finally
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecOutputDataSet = DateTime.Now - this.pv_Debug_dtStartOutputDataSet;

				//AutoSizeColumnsMode가 설정 원상복귀
				oDataGridView.AutoSizeColumnsMode = eDataGridViewAutoSizeColumnsMode;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터셋 반환 타입에 따라 리스트뷰에 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oListView">결과 출력할 리스트뷰 객체</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="bClearOK">데이터그리드뷰에 데이터를 출력하기 전에 초기화</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpOutputDataSetToListView(ComCls.cConst.PE_WEBSQL_TYPE eType, ListView oListView, string sDataSet, DataSet oDataSet, bool bClearOK)
		{
			bool bResult = true;
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };

			ListViewItem[] oListViewItems = null;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartOutputDataSet = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//데이터그리드뷰 초기화
				//---------------------------------------------------------------------------------------------------
				if (bClearOK == true)
				{
					//데이터그리드 모든 행 제거
					oListView.Items.Clear();

					//Application.DoEvents();
				}

				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행 분리
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								//데이터 셋 행수 만큼 리스트뷰 아이템 생성
								oListViewItems = new ListViewItem[saDataSetRows.Length];

								for (int nRow = 0; nRow < saDataSetRows.Length; nRow++)
								{
									//데이터 행 컬럼 분리
									saDataSetCols = saDataSetRows[nRow].Split(saColSepa, StringSplitOptions.None);

									//리스트뷰 한행 생성
									oListViewItems[nRow] = new ListViewItem(saDataSetCols);
									//oListViewItems[nRow] = new ListViewItem { Name = saDataSetCols[0], Text = saDataSetCols[1]};
								}

								//리스트뷰 컬럼수와 데이터셋 컬럼수가 동일한 경우
								if (oListView.Columns.Count == saDataSetCols.Length)
								{
									//리스트뷰에 결과 출력
									oListView.Items.AddRange(oListViewItems);

									//Application.DoEvents();
								}
								else
								{
									bResult = false;
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oDataSet != null && oDataSet.Tables.Count > 0)
						{
							if (oDataSet.Tables[0].Rows.Count > 0)
							{
								//데이터 셋 행수 만큼 리스트뷰 아이템 생성
								oListViewItems = new ListViewItem[oDataSet.Tables[0].Rows.Count];

								for (int nRow = 0; nRow < oDataSet.Tables[0].Rows.Count; nRow++)
								{
									oListViewItems[nRow] = new ListViewItem(oDataSet.Tables[0].Rows[nRow][0].ToString());

									for (int nCol = 1; nCol < oDataSet.Tables[0].Columns.Count; nCol++)
									{
										oListViewItems[nRow].SubItems.Add(oDataSet.Tables[0].Rows[nRow][nCol].ToString());
									}
								}

								//리스트뷰 컬럼수와 데이터셋 컬럼수가 동일한 경우
								if (oListView.Columns.Count == oDataSet.Tables[0].Columns.Count)
								{
									//리스트뷰에 결과 출력
									oListView.Items.AddRange(oListViewItems);

									//Application.DoEvents();
								}
								else
								{
									bResult = false;
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}
			finally
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecOutputDataSet = DateTime.Now - this.pv_Debug_dtStartOutputDataSet;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터셋 반환 타입에 따라 Tree List View에 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oTreeListView">트리 리스트 뷰 객체</param>
		/// <param name="oTreeListViewItem">트리 아이템을 확장한 경우 아이템 객체</param>
		/// <param name="sRootItemParentID">트리 루트 아이템 ID</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="saDataSubItemsKeyIndex">결과 셋트의 트리 아이템의 Key의 서브아이템 인덱스</param>
		/// <param name="saDataSubItemsTextIndex">결과 셋트의 트리 아이템의 Text의 서브아이템 인덱스</param>
		/// <param name="nDispDepth">화면에 오픈할 노드 깊이</param>
		/// <param name="bClearOK">트리뷰에 데이터를 출력하기 전에 초기화</param>
		/// <param name="bTreeItemSetFocusOK">트리뷰 노드에 포커스 주는 여부</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_WpOutputDataSetToTreeListView(ComCls.cConst.PE_WEBSQL_TYPE eType, TreeListView oTreeListView, TreeListViewItem oTreeListViewItem, string sRootItemParentID, string sDataSet, DataSet oDataSet, int[] saDataSubItemsKeyIndex, int[] saDataSubItemsTextIndex, int nDispDepth, bool bClearOK, bool bTreeItemSetFocusOK)
		{
			//---------------------------------------------------------------------------------------------------
			//Web Sql 결과 관련
			//---------------------------------------------------------------------------------------------------
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saDataSubItemsKey = null;
			string[] saDataSubItemsText = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };

			int nRowIndex = 0;
			int nItemIndex = -1;
			TreeListViewItem tlviTreeItem = null;
			string sRootItemID = null;
			bool bRootItemCreateOK = true;
			//bool bUnLimitLoopCheckOK = false;
			//int nUnLimitLoopCount = 0;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartOutputDataSet = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//트리 리스트 뷰 초기화
				//---------------------------------------------------------------------------------------------------
				if (bClearOK == true)
				{
					oTreeListView.Items.Clear();
				}
				//---------------------------------------------------------------------------------------------------
				//트리 리스트 뷰 구성 시작
				//---------------------------------------------------------------------------------------------------
				this.pv_TreeView_eTreeListViewStatus = ComCls.cConst.PE_TREEVIEW_DATASTATUS.START;
				//---------------------------------------------------------------------------------------------------
				//트리 리스트 뷰 루트코드 초기화
				//---------------------------------------------------------------------------------------------------
				sRootItemID = sRootItemParentID.Replace(" ", "");

				if (sRootItemID == "")
				{
					sRootItemID = ComCls.cConst.PC_TREE_ROOT_PARENT_ID;
				}

				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행 분리
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								oTreeListView.BeginUpdate();

								if (saDataSubItemsKeyIndex != null)
								{
									saDataSubItemsKey = new string[saDataSubItemsKeyIndex.Length];
								}

								if (saDataSubItemsTextIndex != null)
								{
									saDataSubItemsText = new string[saDataSubItemsTextIndex.Length];
								}

								while (nRowIndex < saDataSetRows.Length && saDataSubItemsKey != null && saDataSubItemsText != null)
								{
									//---------------------------------------------------------------------------------------------------
									//한 행의 모든 컬럼 분리(OBJECTID, PAR_OBJECTID, GRP_OBJECTID, CODE, PATTERN, KNAME, CID)
									//---------------------------------------------------------------------------------------------------
									saDataSetCols = saDataSetRows[nRowIndex].Split(saColSepa, StringSplitOptions.None);
									//---------------------------------------------------------------------------------------------------
									//트리 리스트뷰 아이템의 서브아이템 데이터 생성
									//---------------------------------------------------------------------------------------------------
									for (int nIndex = 0; nIndex < saDataSubItemsKey.Length; nIndex++)
									{
										saDataSubItemsKey[nIndex] = saDataSetCols[saDataSubItemsKeyIndex[nIndex]];
										saDataSubItemsText[nIndex] = saDataSetCols[saDataSubItemsTextIndex[nIndex]];
									}
									//---------------------------------------------------------------------------------------------------
									//트리 리스트 뷰 아이템 생성
									//---------------------------------------------------------------------------------------------------
									if (this.pf_TreeAddItem(oTreeListView, sRootItemID, ref tlviTreeItem, saDataSetCols, saDataSubItemsKey, saDataSubItemsText, ref nRowIndex, bRootItemCreateOK) == true)
									{
										//---------------------------------------------------------------------------------------------------
										//트리 노드 열기(DB:1레벨부터 시작, C#:0레벨부터 시작)
										//---------------------------------------------------------------------------------------------------
										if (tlviTreeItem != null)
										{
											if (tlviTreeItem.Level < nDispDepth - 1 && tlviTreeItem.IsExpanded == false)
											{
												tlviTreeItem.Expand();
											}
										}
									}
									else
									{
										MessageBox.Show(ComCls.cConst.PC_ERROR_TREEVIEW_DATA, ComCls.cConst.PC_ERROR_TREEVIEW_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
										break;
									}

									//트리뷰 무한루프 확인
									//if (this.pf_WpOutputDataSetToTreeViewLoopCheck(oTreeView,
									//                                                tnNode,
									//                                                ref bUnLimitLoopCheckOK,
									//                                                ref nUnLimitLoopCount) == true) break;
								}

								oTreeListView.EndUpdate();

								if (bTreeItemSetFocusOK == true)
								{
									//트리 노드를 펼쳐서 다시 읽을때
									if (oTreeListViewItem != null)
									{
										this.pf_TreeItemContains(oTreeListView.Items[0], oTreeListViewItem.Name, ref nItemIndex);

										if (nItemIndex > -1)
										{
											oTreeListView.Items[nItemIndex].Selected = true;
										}
									}
									//처음 읽을때(루트 == -1)
									else
									{
										if (oTreeListView.Items != null && oTreeListView.Items.Count > 0)
										{
											oTreeListView.Items[0].Selected = true;
											oTreeListView.Focus();
										}
									}
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oDataSet != null && oDataSet.Tables.Count > 0)
						{
							if (oDataSet.Tables[0].Rows.Count > 0)
							{
								oTreeListView.BeginUpdate();

								if (saDataSubItemsKeyIndex != null)
								{
									saDataSubItemsKey = new string[saDataSubItemsKeyIndex.Length];
								}

								if (saDataSubItemsTextIndex != null)
								{
									saDataSubItemsText = new string[saDataSubItemsTextIndex.Length];
								}

								while (nRowIndex < oDataSet.Tables[0].Rows.Count && saDataSubItemsKey != null && saDataSubItemsText != null)
								{
									//---------------------------------------------------------------------------------------------------
									//트리 리스트뷰 아이템의 서브아이템 데이터 생성
									//---------------------------------------------------------------------------------------------------
									for (int nIndex = 0; nIndex < saDataSubItemsKey.Length; nIndex++)
									{
										saDataSubItemsKey[nIndex] = oDataSet.Tables[0].Rows[nRowIndex][saDataSubItemsKeyIndex[nIndex]].ToString();
										saDataSubItemsText[nIndex] = oDataSet.Tables[0].Rows[nRowIndex][saDataSubItemsTextIndex[nIndex]].ToString();
									}
									//---------------------------------------------------------------------------------------------------
									//트리 리스트 뷰 아이템 생성
									//---------------------------------------------------------------------------------------------------
									if (this.pf_TreeAddItem(oTreeListView, sRootItemID, ref tlviTreeItem, oDataSet.Tables[0].Rows[nRowIndex], saDataSubItemsKey, saDataSubItemsText, ref nRowIndex, bRootItemCreateOK) == true)
									{
										//---------------------------------------------------------------------------------------------------
										//트리 노드 열기(DB:1레벨부터 시작, C#:0레벨부터 시작)
										//---------------------------------------------------------------------------------------------------
										if (tlviTreeItem != null)
										{
											if (tlviTreeItem.Level < nDispDepth - 1 && tlviTreeItem.IsExpanded == false)
											{
												tlviTreeItem.Expand();
											}
										}
									}
									else
									{
										MessageBox.Show(ComCls.cConst.PC_ERROR_TREEVIEW_DATA, ComCls.cConst.PC_ERROR_TREEVIEW_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
										break;
									}

									//트리뷰 무한루프 확인
									//if (this.pf_WpOutputDataSetToTreeViewLoopCheck(oTreeView,
									//                                                tnNode,
									//                                                ref bUnLimitLoopCheckOK,
									//                                                ref nUnLimitLoopCount) == true) break;
								}

								oTreeListView.EndUpdate();

								if (bTreeItemSetFocusOK == true)
								{
									//트리 노드를 펼쳐서 다시 읽을때
									if (oTreeListViewItem != null)
									{
										this.pf_TreeItemContains(oTreeListView.Items[0], oTreeListViewItem.Name, ref nItemIndex);

										if (nItemIndex > -1)
										{
											oTreeListView.Items[nItemIndex].Selected = true;
										}
									}
									//처음 읽을때(루트 == -1)
									else
									{
										if (oTreeListView.Items != null && oTreeListView.Items.Count > 0)
										{
											oTreeListView.Items[0].Selected = true;
											oTreeListView.Focus();
										}
									}
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				oTreeListView.EndUpdate();
				//---------------------------------------------------------------------------------------------------
				//트리뷰 구성 종료
				//---------------------------------------------------------------------------------------------------
				this.pv_TreeView_eTreeListViewStatus = ComCls.cConst.PE_TREEVIEW_DATASTATUS.COMPLETE;
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecOutputDataSet = DateTime.Now - this.pv_Debug_dtStartOutputDataSet;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 결과 데이터 셋을 데이터셋 반환 타입에 따라 Tree View에 출력</summary>
		/// <param name="eType">데이터 셋 반환 타입(PARSE/XML)</param>
		/// <param name="oTreeView">트리 객체</param>
		/// <param name="oTreeNode">트리 노드를 확장한 경우 노드 객체</param>
		/// <param name="sRootNodeParentID">트리 루트 ID</param>
		/// <param name="sDataSet">데이터 셋 문자열(PARSE 타입)</param>
		/// <param name="oDataSet">데이터 셋 객체(XML 타입)</param>
		/// <param name="nDispDepth">화면에 오픈할 노드 깊이</param>
		/// <param name="bClearOK">트리뷰에 데이터를 출력하기 전에 초기화</param>
		/// <param name="bTreeNodeSetFocusOK">트리뷰 노드에 포커스 주는 여부</param>
		/// <returns>void</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public void pf_WpOutputDataSetToTreeView(ComCls.cConst.PE_WEBSQL_TYPE eType, TreeView oTreeView, TreeNode oTreeNode, string sRootNodeParentID, string sDataSet, DataSet oDataSet, int nDispDepth, bool bClearOK, bool bTreeNodeSetFocusOK)
		{
			//---------------------------------------------------------------------------------------------------
			//Web Sql 결과 관련
			//---------------------------------------------------------------------------------------------------
			string[] saDataSetRows = null;
			string[] saDataSetCols = null;
			string[] saRowSepa = new string[] { ComCls.cConst.PC_SEPARATOR_ROW };
			string[] saColSepa = new string[] { ComCls.cConst.PC_SEPARATOR_COL };

			int nRowIndex = 0;
			TreeNode tnTreeNode = null;
			string sRootNodeID = null;
			bool bRootCreateOK = true;
			//bool bUnLimitLoopCheckOK = false;
			//int nUnLimitLoopCount = 0;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시작 시간
				//---------------------------------------------------------------------------------------------------
				this.pv_Debug_dtStartOutputDataSet = DateTime.Now;
				//---------------------------------------------------------------------------------------------------
				//트리뷰 초기화
				//---------------------------------------------------------------------------------------------------
				if (bClearOK == true)
				{
					oTreeView.Nodes.Clear();
				}
				//---------------------------------------------------------------------------------------------------
				//트리뷰 깜박임 방지
				//---------------------------------------------------------------------------------------------------
				oTreeView.SelectedNode = null;
				//---------------------------------------------------------------------------------------------------
				//트리뷰 구성 시작
				//---------------------------------------------------------------------------------------------------
				this.pv_TreeView_eTreeViewStatus = ComCls.cConst.PE_TREEVIEW_DATASTATUS.START;
				//---------------------------------------------------------------------------------------------------
				//트리뷰 루트코드 초기화
				//---------------------------------------------------------------------------------------------------
				sRootNodeID = sRootNodeParentID.Replace(" ", "");

				if (sRootNodeID == "")
				{
					sRootNodeID = ComCls.cConst.PC_TREE_ROOT_PARENT_ID;
				}
				//---------------------------------------------------------------------------------------------------
				//트리뷰에서 중간 노드를 확장하고 손자 노드가 없는경우 DB 읽어서 추가하기 위해 초기화
				//---------------------------------------------------------------------------------------------------
				if (oTreeNode != null)
				{
					//오픈한 노드의 자식노드 초기화
					oTreeNode.Nodes.Clear();

					//시작 노드를 오픈한 노드로 지정
					tnTreeNode = oTreeNode;

					//루트 노드에 생성하지 않도록
					bRootCreateOK = false;
				}

				switch (eType)
				{
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 PARSE인 경우
					//--------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
						if (sDataSet != null && sDataSet != "")
						{
							//데이터 셋 행 분리
							saDataSetRows = sDataSet.Split(saRowSepa, StringSplitOptions.None);

							if (saDataSetRows != null && saDataSetRows.Length > 0)
							{
								oTreeView.BeginUpdate();

								while (nRowIndex < saDataSetRows.Length)
								{
									//---------------------------------------------------------------------------------------------------
									//한 행의 모든 컬럼 분리(OBJECTID, PAR_OBJECTID, GRP_OBJECTID, CODE, PATTERN, KNAME, CID)
									//---------------------------------------------------------------------------------------------------
									saDataSetCols = saDataSetRows[nRowIndex].Split(saColSepa, StringSplitOptions.None);
									//---------------------------------------------------------------------------------------------------
									//트리 노드 생성
									//---------------------------------------------------------------------------------------------------
									if (this.pf_TreeAddNode(oTreeView, sRootNodeID, ref tnTreeNode, saDataSetCols, ref nRowIndex, bRootCreateOK) == true)
									{
										//---------------------------------------------------------------------------------------------------
										//트리 노드 열기(DB:1레벨부터 시작, C#:0레벨부터 시작)
										//---------------------------------------------------------------------------------------------------
										if (tnTreeNode != null)
										{
											if (tnTreeNode.Level < nDispDepth - 1 && tnTreeNode.IsExpanded == false)
											{
												tnTreeNode.Expand();
											}
										}
									}
									else
									{
										MessageBox.Show(ComCls.cConst.PC_ERROR_TREEVIEW_DATA, ComCls.cConst.PC_ERROR_TREEVIEW_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
										break;
									}

									//트리뷰 무한루프 확인
									//if (this.pf_WpOutputDataSetToTreeViewLoopCheck(oTreeView,
									//                                                tnNode,
									//                                                ref bUnLimitLoopCheckOK,
									//                                                ref nUnLimitLoopCount) == true) break;
								}

								oTreeView.EndUpdate();

								if (bTreeNodeSetFocusOK == true)
								{
									//트리 노드를 펼쳐서 다시 읽을때
									if (oTreeNode != null)
									{
										oTreeView.SelectedNode = oTreeNode;
									}
									//처음 읽을때(루트 == -1)
									else
									{
										if (oTreeView.Nodes != null && oTreeView.Nodes.Count > 0)
										{
											oTreeView.SelectedNode = oTreeView.Nodes[0];
											oTreeView.Focus();
										}
									}
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
					//데이터셋 반환 타입이 XML인 경우
					//---------------------------------------------------------------------------------------------------
					case ComCls.cConst.PE_WEBSQL_TYPE.XML:
						if (oDataSet != null && oDataSet.Tables.Count > 0)
						{
							if (oDataSet.Tables[0].Rows.Count > 0)
							{
								oTreeView.BeginUpdate();

								while (nRowIndex < oDataSet.Tables[0].Rows.Count)
								{
									//---------------------------------------------------------------------------------------------------
									//트리 노드 생성
									//---------------------------------------------------------------------------------------------------
									if (this.pf_TreeAddNode(oTreeView, sRootNodeID, ref tnTreeNode, oDataSet.Tables[0].Rows[nRowIndex], ref nRowIndex, bRootCreateOK) == true)
									{
										//---------------------------------------------------------------------------------------------------
										//트리 노드 열기(DB:1레벨부터 시작, C#:0레벨부터 시작)
										//---------------------------------------------------------------------------------------------------
										if (tnTreeNode != null)
										{
											if (tnTreeNode.Level < nDispDepth - 1 && tnTreeNode.IsExpanded == false)
											{
												tnTreeNode.Expand();
											}
										}
									}
									else
									{
										MessageBox.Show(ComCls.cConst.PC_ERROR_TREEVIEW_DATA, ComCls.cConst.PC_ERROR_TREEVIEW_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
										break;
									}

									//트리뷰 무한루프 확인
									//if (this.pf_WpOutputDataSetToTreeViewLoopCheck(oTreeView,
									//                                                tnNode,
									//                                                ref bUnLimitLoopCheckOK,
									//                                                ref nUnLimitLoopCount) == true) break;
								}

								oTreeView.EndUpdate();

								if (bTreeNodeSetFocusOK == true)
								{
									//트리 노드를 펼쳐서 다시 읽을때
									if (oTreeNode != null)
									{
										oTreeView.SelectedNode = oTreeNode;
									}
									//처음 읽을때(루트 == -1)
									else
									{
										if (oTreeView.Nodes != null && oTreeView.Nodes.Count > 0)
										{
											oTreeView.SelectedNode = oTreeView.Nodes[0];
											oTreeView.Focus();
										}
									}
								}
							}
						}

						break;
					//---------------------------------------------------------------------------------------------------
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				oTreeView.EndUpdate();
				//---------------------------------------------------------------------------------------------------
				//트리뷰 구성 종료
				//---------------------------------------------------------------------------------------------------
				this.pv_TreeView_eTreeViewStatus = ComCls.cConst.PE_TREEVIEW_DATASTATUS.COMPLETE;
				//---------------------------------------------------------------------------------------------------
				//DataSet 출력 시간 계산
				//---------------------------------------------------------------------------------------------------
				pv_Debug_tsIntervalSecOutputDataSet = DateTime.Now - this.pv_Debug_dtStartOutputDataSet;
			}
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>트리뷰 노드를 생성하는 도중 데이터이상으로 무한 루프에 빠지는지 확인</summary>
		/// <param name="oTreeView">트리뷰 객체 핸들</param>
		/// <param name="oTreeParentNode">현재 생성중인 노드의 부모 노드 객체 핸들</param>
		/// <param name="bUnLimitLoopCheckStartOK">무한 루프 확인 시작 여부</param>
		/// <param name="nUnLimitLoopCount">트리뷰 노드를 생성하는 도중 트리뷰 루트노드 까지 연속으로 오는 횟수</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpOutputDataSetToTreeViewLoopCheck(TreeView oTreeView, TreeNode oTreeParentNode, ref bool bUnLimitLoopCheckStartOK, ref int nUnLimitLoopCount)
		{
			bool bResult = false;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//원리 -		루트 아래로 노드가 생성되고 다시 위 방향으로 올라와서
				//			루트 아래에 새 자식노드를 생성하고(이렇게 반복...) 하는 경우
				//			루트 노드에 계속 머무르는 경우가 발생하게 되면 무한 루프를 의심
				//			(데이터가 잘못된 경우 발생 가능 함)
				//---------------------------------------------------------------------------------------------------
				if (oTreeParentNode != null)
				{
					if (oTreeParentNode.Level > 0)
					{
						bUnLimitLoopCheckStartOK = true;
					}

					if (oTreeParentNode.Level == 0)// && bUnLimitLoopCheckStartOK == true)
					{
						if (oTreeView.Nodes[0] == oTreeParentNode)
						{
							nUnLimitLoopCount++;

							if (nUnLimitLoopCount > 1000)
							{
								MessageBox.Show(ComCls.cConst.PC_ERROR_TREEVIEW_UNLIMITID_LOOP, ComCls.cConst.PC_ERROR_TREEVIEW_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);

								bResult = true;
							}
						}
						else nUnLimitLoopCount = 0;
					}
					else nUnLimitLoopCount = 0;
				}
				else bResult = true;
				//---------------------------------------------------------------------------------------------------
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기</summary>
		/// <param name="eMode">Sql 실행 모드(CRUD)</param>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="sWebDataSet">웹 페이지를 통해 반환된 결과 전체(페이지 소스)</param>
		/// <param name="sDataSet">결과 셋 문자열 전달</param>
		/// <param name="oDataSet">결과 셋 객체 전달</param>
		/// <param name="nRowCount">반환된 행수 전달</param>
		/// <param name="nColCount">반환된 열수 전달</param>
		/// <param name="sErrorMsg">에러 발생 시 에러 메시지 전달</param>
		/// <param name="sSID">트랜잭션 처리시 세션 ID 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpReadDataSet(ComCls.cConst.PE_WEBSQL_MODE eMode, ComCls.cConst.PE_WEBSQL_TYPE eType, string sWebDataSet, ref string sDataSet, ref DataSet oDataSet, ref int nRowCount, ref int nColCount, ref string sErrorMsg, ref string sSID)
		{
			bool bResult = false;

			string[] saDataSet = null;
			string[] saDataSetMem = null;
			string[] saDataSetSub = null;
			string[] saRecordInfo = null;

			StringReader srDataSet = null;

			string[] saHeaderSepa = new string[] { ComCls.cConst.PC_SEPARATOR_HEADER };
			string[] saRecordSepa = new string[] { ComCls.cConst.PC_SEPARATOR_RECORD };
			string[] saFooterSepa = new string[] { ComCls.cConst.PC_SEPARATOR_FOOTER };
			string[] saErrorSepa = new string[] { ComCls.cConst.PC_WEBPARSE_ERROR };

			try
			{
				//웹 페이지 데이터가 있으면
				if (sWebDataSet != null && sWebDataSet != "")
				{
					switch (eType)
					{
						//---------------------------------------------------------------------------------------------------
						//데이터셋 반환 타입이 PARSE인 경우
						//---------------------------------------------------------------------------------------------------
						case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
							//웹 페이지 데이터에서 헤더 앞부분 자르기
							saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

							if (saDataSet != null && saDataSet.Length > 1)
							{
								//웹 페이지 데이터에서 꼬리 뒷부분 자르기
								saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

								if (saDataSetMem != null && saDataSetMem.Length > 0)
								{
									//웹 페이지 데이터에서 레코드 정보부분 자르기
									saDataSetSub = saDataSetMem[0].Split(saRecordSepa, StringSplitOptions.None);

									//에러 확인
									if (saDataSetSub[0].IndexOf(ComCls.cConst.PC_WEBPARSE_ERROR) == -1)
									{
										if (saDataSetSub != null && saDataSetSub.Length == 2)
										{
											//레코드 정보(행수, 열수) 구하기
											saRecordInfo = saDataSetSub[0].Split(',');

											if (saRecordInfo != null && saRecordInfo.Length == 2)
											{
												////일반적으로 Sql을 실행해서 정상적으로 행/열 수가 넘어온 경우
												//if (saRecordInfo[0] != "True")
												//{
												//    nRowCount = Convert.ToInt32(saRecordInfo[0]);
												//    nColCount = Convert.ToInt32(saRecordInfo[1]);
												//}
												////트랜잭션 처리를 하는경우 "True,abcde123..." 형식의 결과와 세션 ID 값이 넘어온다
												//else
												//{
												//    nRowCount = 1;
												//    nColCount = 1;
												//}

												switch (eMode)
												{
													case ComCls.cConst.PE_WEBSQL_MODE.R:
														nRowCount = Convert.ToInt32(saRecordInfo[0]);
														nColCount = Convert.ToInt32(saRecordInfo[1]);

														sSID = null;

														break;
													case ComCls.cConst.PE_WEBSQL_MODE.CUD:
														nRowCount = Convert.ToInt32(saRecordInfo[0]);
														nColCount = Convert.ToInt32(saRecordInfo[1]);

														sSID = null;

														break;
													case ComCls.cConst.PE_WEBSQL_MODE.TCUD:
														nRowCount = Convert.ToInt32(saRecordInfo[0]);
														nColCount = 1;

														sSID = saRecordInfo[1];

														break;
												}
											}

											//웹 페이지 데이터에서 순수하게 데이터 셋 부분을 UrlDecoding
											sDataSet = pf_WpHtmlDecodeAll(saDataSetSub[1]);

											bResult = true;
										}
									}
									else
									{
										saDataSetMem = null;

										saDataSetMem = saDataSetSub[0].Split(saErrorSepa, StringSplitOptions.None);

										if (saDataSetMem != null && saDataSetMem.Length == 2)
										{
											sErrorMsg = pf_WpHtmlDecodeAll(saDataSetMem[1]);
										}
									}
								}
							}

							break;
						//---------------------------------------------------------------------------------------------------
						//데이터셋 반환 타입이 XML인 경우
						//---------------------------------------------------------------------------------------------------
						case ComCls.cConst.PE_WEBSQL_TYPE.XML:
							//웹 페이지 데이터에서 헤더 앞부분 자르기
							saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

							if (saDataSet != null && saDataSet.Length > 1)
							{
								//웹 페이지 데이터에서 꼬리 뒷부분 자르기
								saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

								if (saDataSetMem != null && saDataSetMem.Length > 0)
								{
									//에러 확인
									if (saDataSetMem[0].IndexOf(ComCls.cConst.PC_WEBPARSE_ERROR) == -1)
									{
										//웹 페이지 데이터에서 순수하게 데이터 셋 부분을 UrlDecoding
										sDataSet = pf_WpHtmlDecodeAll(saDataSetMem[0]);

										if (sDataSet != null && sDataSet != "")
										{
											//데이터 셋을 바운딩 하기 위해 XML 에서 읽기
											oDataSet = new DataSet();
											srDataSet = new System.IO.StringReader(sDataSet);

											oDataSet.ReadXml(srDataSet);

											if (oDataSet != null && oDataSet.Tables.Count > 0)
											{
												switch (eMode)
												{
													case ComCls.cConst.PE_WEBSQL_MODE.R:
														nRowCount = oDataSet.Tables[0].Rows.Count;
														nColCount = oDataSet.Tables[0].Columns.Count;

														break;
													case ComCls.cConst.PE_WEBSQL_MODE.CUD:
														nRowCount = Convert.ToInt32(oDataSet.Tables[0].Rows[0][0].ToString());
														nColCount = 1;

														break;
													case ComCls.cConst.PE_WEBSQL_MODE.TCUD:
														nRowCount = Convert.ToInt32(oDataSet.Tables[0].Rows[0][0].ToString());
														nColCount = 1;

														sSID = oDataSet.Tables[0].Rows[0][1].ToString();


														break;
												}
											}

											bResult = true;
										}
									}
									else
									{
										saDataSetMem = saDataSetMem[0].Split(saErrorSepa, StringSplitOptions.None);

										if (saDataSetMem != null && saDataSetMem.Length == 2)
										{
											sErrorMsg = pf_WpHtmlDecodeAll(saDataSetMem[1]);
										}
									}
								}
							}

							break;
						//---------------------------------------------------------------------------------------------------
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기</summary>
		/// <param name="eMode">Sql 실행 모드(CRUD)</param>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="sWebDataSet">웹 페이지를 통해 반환된 결과 전체(페이지 소스)</param>
		/// <param name="sDataSet">결과 셋 문자열 전달</param>
		/// <param name="oDataSet">결과 셋 객체 전달</param>
		/// <param name="nRowCount">반환된 행수 전달</param>
		/// <param name="nColCount">반환된 열수 전달</param>
		/// <param name="sErrorMsg">에러 발생 시 에러 메시지 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpReadDataSet(ComCls.cConst.PE_WEBSQL_MODE eMode, ComCls.cConst.PE_WEBSQL_TYPE eType, string sWebDataSet, ref string sDataSet, ref DataSet oDataSet, ref int nRowCount, ref int nColCount, ref string sErrorMsg)
		{
			bool bResult = false;

			string[] saDataSet = null;
			string[] saDataSetMem = null;
			string[] saDataSetSub = null;
			string[] saRecordInfo = null;

			StringReader srDataSet = null;

			string[] saHeaderSepa = new string[] { ComCls.cConst.PC_SEPARATOR_HEADER };
			string[] saRecordSepa = new string[] { ComCls.cConst.PC_SEPARATOR_RECORD };
			string[] saFooterSepa = new string[] { ComCls.cConst.PC_SEPARATOR_FOOTER };
			string[] saErrorSepa = new string[] { ComCls.cConst.PC_WEBPARSE_ERROR };

			try
			{
				//웹 페이지 데이터가 있으면
				if (sWebDataSet != null && sWebDataSet != "")
				{
					switch (eType)
					{
						//---------------------------------------------------------------------------------------------------
						//데이터셋 반환 타입이 PARSE인 경우
						//---------------------------------------------------------------------------------------------------
						case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
							//웹 페이지 데이터에서 헤더 앞부분 자르기
							saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

							if (saDataSet != null && saDataSet.Length > 1)
							{
								//웹 페이지 데이터에서 꼬리 뒷부분 자르기
								saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

								if (saDataSetMem != null && saDataSetMem.Length > 0)
								{
									//웹 페이지 데이터에서 레코드 정보부분 자르기
									saDataSetSub = saDataSetMem[0].Split(saRecordSepa, StringSplitOptions.None);

									//에러 확인
									if (saDataSetSub[0].IndexOf(ComCls.cConst.PC_WEBPARSE_ERROR) == -1)
									{
										if (saDataSetSub != null && saDataSetSub.Length == 2)
										{
											//레코드 정보(행수, 열수) 구하기
											saRecordInfo = saDataSetSub[0].Split(',');

											if (saRecordInfo != null && saRecordInfo.Length == 2)
											{
												switch (eMode)
												{
													case ComCls.cConst.PE_WEBSQL_MODE.R:
														nRowCount = Convert.ToInt32(saRecordInfo[0]);
														nColCount = Convert.ToInt32(saRecordInfo[1]);

														break;
													case ComCls.cConst.PE_WEBSQL_MODE.CUD:
														nRowCount = Convert.ToInt32(saRecordInfo[0]);
														nColCount = Convert.ToInt32(saRecordInfo[1]);

														break;
												}
											}

											//웹 페이지 데이터에서 순수하게 데이터 셋 부분을 UrlDecoding
											sDataSet = pf_WpHtmlDecodeAll(saDataSetSub[1]);

											bResult = true;
										}
									}
									else
									{
										saDataSetMem = null;

										saDataSetMem = saDataSetSub[0].Split(saErrorSepa, StringSplitOptions.None);

										if (saDataSetMem != null && saDataSetMem.Length == 2)
										{
											sErrorMsg = pf_WpHtmlDecodeAll(saDataSetMem[1]);
										}
									}
								}
							}

							break;
						//---------------------------------------------------------------------------------------------------
						//데이터셋 반환 타입이 XML인 경우
						//---------------------------------------------------------------------------------------------------
						case ComCls.cConst.PE_WEBSQL_TYPE.XML:
							//웹 페이지 데이터에서 헤더 앞부분 자르기
							saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

							if (saDataSet != null && saDataSet.Length > 0)
							{
								//웹 페이지 데이터에서 꼬리 뒷부분 자르기
								saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

								if (saDataSetMem != null && saDataSetMem.Length > 0)
								{
									//에러 확인
									if (saDataSetMem[0].IndexOf(ComCls.cConst.PC_WEBPARSE_ERROR) == -1)
									{
										//웹 페이지 데이터에서 순수하게 데이터 셋 부분을 UrlDecoding
										sDataSet = pf_WpHtmlDecodeAll(saDataSetMem[0]);

										if (sDataSet != null && sDataSet != "")
										{
											//데이터 셋을 바운딩 하기 위해 XML 에서 읽기
											oDataSet = new DataSet();
											srDataSet = new System.IO.StringReader(sDataSet);

											oDataSet.ReadXml(srDataSet);

											if (oDataSet != null && oDataSet.Tables.Count > 0)
											{
												switch (eMode)
												{
													case ComCls.cConst.PE_WEBSQL_MODE.R:
														nRowCount = oDataSet.Tables[0].Rows.Count;
														nColCount = oDataSet.Tables[0].Columns.Count;

														break;
													case ComCls.cConst.PE_WEBSQL_MODE.CUD:
														nRowCount = Convert.ToUInt16(oDataSet.Tables[0].Rows[0][0].ToString());
														nColCount = 1;

														break;
												}
											}

											bResult = true;
										}
									}
									else
									{
										saDataSetMem = saDataSetMem[0].Split(saErrorSepa, StringSplitOptions.None);

										if (saDataSetMem != null && saDataSetMem.Length == 2)
										{
											sErrorMsg = pf_WpHtmlDecodeAll(saDataSetMem[1]);
										}
									}
								}
							}

							break;
						//---------------------------------------------------------------------------------------------------
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기</summary>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="sWebDataSet">웹 페이지를 통해 반환된 결과 전체(페이지 소스)</param>
		/// <param name="sDataSet">결과 셋 문자열 전달</param>
		/// <param name="oDataSet">결과 셋 객체 전달</param>
		/// <param name="nRowCount">반환된 행수 전달</param>
		/// <param name="nColCount">반환된 열수 전달</param>
		/// <param name="sErrorMsg">에러 발생 시 에러 메시지 전달</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpReadDataSet(ComCls.cConst.PE_WEBSQL_TYPE eType, string sWebDataSet, ref string sDataSet, ref DataSet oDataSet, ref int nRowCount, ref int nColCount, ref string sErrorMsg)
		{
			bool bResult = false;

			string[] saDataSet = null;
			string[] saDataSetMem = null;
			string[] saDataSetSub = null;
			string[] saRecordInfo = null;

			StringReader srDataSet = null;

			string[] saHeaderSepa = new string[] { ComCls.cConst.PC_SEPARATOR_HEADER };
			string[] saRecordSepa = new string[] { ComCls.cConst.PC_SEPARATOR_RECORD };
			string[] saFooterSepa = new string[] { ComCls.cConst.PC_SEPARATOR_FOOTER };
			string[] saErrorSepa = new string[] { ComCls.cConst.PC_WEBPARSE_ERROR };

			try
			{
				//웹 페이지 데이터가 있으면
				if (sWebDataSet != null && sWebDataSet != "")
				{
					switch (eType)
					{
						//---------------------------------------------------------------------------------------------------
						//데이터셋 반환 타입이 PARSE인 경우
						//---------------------------------------------------------------------------------------------------
						case ComCls.cConst.PE_WEBSQL_TYPE.PARSE:
							//웹 페이지 데이터에서 헤더 앞부분 자르기
							saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

							if (saDataSet != null && saDataSet.Length > 1)
							{
								//웹 페이지 데이터에서 꼬리 뒷부분 자르기
								saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

								if (saDataSetMem != null && saDataSetMem.Length > 0)
								{
									//웹 페이지 데이터에서 레코드 정보부분 자르기
									saDataSetSub = saDataSetMem[0].Split(saRecordSepa, StringSplitOptions.None);

									//에러 확인
									if (saDataSetSub[0].IndexOf(ComCls.cConst.PC_WEBPARSE_ERROR) == -1)
									{
										if (saDataSetSub != null && saDataSetSub.Length == 2)
										{
											//레코드 정보(행수, 열수) 구하기
											saRecordInfo = saDataSetSub[0].Split(',');

											if (saRecordInfo != null && saRecordInfo.Length == 2)
											{
												nRowCount = Convert.ToInt32(saRecordInfo[0]);
												nColCount = Convert.ToInt32(saRecordInfo[1]);
											}

											//웹 페이지 데이터에서 순수하게 데이터 셋 부분을 UrlDecoding
											sDataSet = pf_WpHtmlDecodeAll(saDataSetSub[1]);

											bResult = true;
										}
									}
									else
									{
										saDataSetMem = null;

										saDataSetMem = saDataSetSub[0].Split(saErrorSepa, StringSplitOptions.None);

										if (saDataSetMem != null && saDataSetMem.Length == 2)
										{
											sErrorMsg = pf_WpHtmlDecodeAll(saDataSetMem[1]);
										}
									}
								}
							}

							break;
						//---------------------------------------------------------------------------------------------------
						//데이터셋 반환 타입이 XML인 경우
						//---------------------------------------------------------------------------------------------------
						case ComCls.cConst.PE_WEBSQL_TYPE.XML:
							//웹 페이지 데이터에서 헤더 앞부분 자르기
							saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

							if (saDataSet != null && saDataSet.Length > 0)
							{
								//웹 페이지 데이터에서 꼬리 뒷부분 자르기
								saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

								if (saDataSetMem != null && saDataSetMem.Length > 0)
								{
									//에러 확인
									if (saDataSetMem[0].IndexOf(ComCls.cConst.PC_WEBPARSE_ERROR) == -1)
									{
										//웹 페이지 데이터에서 순수하게 데이터 셋 부분을 UrlDecoding
										sDataSet = pf_WpHtmlDecodeAll(saDataSetMem[0]);

										if (sDataSet != null && sDataSet != "")
										{
											//데이터 셋을 바운딩 하기 위해 XML 에서 읽기
											oDataSet = new DataSet();
											srDataSet = new System.IO.StringReader(sDataSet);

											oDataSet.ReadXml(srDataSet);

											if (oDataSet != null && oDataSet.Tables.Count > 0)
											{
												nRowCount = oDataSet.Tables[0].Rows.Count;
												nColCount = oDataSet.Tables[0].Columns.Count;
											}

											bResult = true;
										}
									}
									else
									{
										saDataSetMem = saDataSetMem[0].Split(saErrorSepa, StringSplitOptions.None);

										if (saDataSetMem != null && saDataSetMem.Length == 2)
										{
											sErrorMsg = pf_WpHtmlDecodeAll(saDataSetMem[1]);
										}
									}
								}
							}

							break;
						//---------------------------------------------------------------------------------------------------
					}
				}
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 페이지를 통해 반환된 결과에서 데이터 셋 분리해서 읽어내기</summary>
		/// <param name="sWebDataSet">웹 페이지를 통해 반환된 결과 전체(페이지 소스)</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpReadDataSet(string sWebDataSet)
		{
			string sDataSet = null;
			string[] saDataSet = null;
			string[] saDataSetMem = null;

			string[] saHeaderSepa = new string[] { ComCls.cConst.PC_SEPARATOR_HEADER };
			string[] saFooterSepa = new string[] { ComCls.cConst.PC_SEPARATOR_FOOTER };

			try
			{
				//웹 페이지 데이터가 있으면
				if (sWebDataSet != null && sWebDataSet != "")
				{
					//웹 페이지 데이터에서 헤더 앞부분 자르기
					saDataSet = sWebDataSet.Split(saHeaderSepa, StringSplitOptions.None);

					if (saDataSet != null && saDataSet.Length > 0)
					{
						//웹 페이지 데이터에서 꼬리 뒷부분 자르기
						saDataSetMem = saDataSet[1].Split(saFooterSepa, StringSplitOptions.None);

						if (saDataSetMem != null && saDataSetMem.Length > 0)
						{
							//웹 페이지 데이터에서 순수하게 데이터 셋 부분
							//웹 페이지에서 변환된 문자들을 원래 문자로 디코딩
							sDataSet = pf_WpHtmlDecodeAll(saDataSetMem[0]);
						}
					}
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sDataSet;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 페이지에 넘길 주소(Sql 인자부분)에서 "&"를 찾아 "%26"으로 변환</summary>
		/// <param name="sData">웹 페이지 주소에 넘길 데이터</param>
		/// <returns>string</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public string pf_WpUrlEncode(string sUrlArg)
		{
			string sResult = null;

			try
			{
				sResult = sUrlArg.Replace("&", "%26");
			}
			catch (Exception ex)
			{
				throw ex;
			}

			return sResult;
		}
		///-------------------------------------------------------------------------------------------------------------------------
		/// <summary>웹 파즈 경로에 넘겨진 인자의 유효성 검증</summary>
		/// <param name="oQueryString">웹 페이지 Request.QueryString 객체</param>
		/// <param name="eMode">Sql 실행 모드(CRUD)</param>
		/// <param name="eType">데이터셋 반환 타입(PARSE/XML)</param>
		/// <param name="eStyle">Sql 실행 방식(TEXT/SP)</param>
		/// <param name="sCommand">Embeded Sql/Stord Procedure Name</param>
		/// <param name="saPaNames">Stord Procedure 인자 명칭</param>
		/// <param name="saPaValues">Stord Procedure 인자 값</param>
		/// <param name="sSID">세션 ID(트랜젝션 처리 모드인 경우)</param>
		/// <returns>bool</returns>
		///-------------------------------------------------------------------------------------------------------------------------
		public bool pf_WpUrlValidationCheck(NameValueCollection oQueryString, ref ComCls.cConst.PE_WEBSQL_MODE eMode, ref ComCls.cConst.PE_WEBSQL_TYPE eType, ref ComCls.cConst.PE_WEBSQL_STYLE eStyle, ref string sCommand, ref string[] saPaNames, ref string[] saPaValues, ref string sSID)
		{
			bool bResult = false;

			try
			{
				//---------------------------------------------------------------------------------------------------
				//인자 개수 확인(PARSE 타입인 경우 적어도 인자가 3개 이므로)
				//---------------------------------------------------------------------------------------------------
				if (oQueryString.AllKeys.Length >= 4)
				{
					//---------------------------------------------------------------------------------------------------
					//Sql 작업 모드(CRUD) 확인 : Mode
					//---------------------------------------------------------------------------------------------------
					if (oQueryString.AllKeys[0] == ComCls.cConst.PC_WEBSQL_MODE)
					{
						if (oQueryString[ComCls.cConst.PC_WEBSQL_MODE] == ComCls.cConst.PC_WEBSQL_MODE_R)
						{
							eMode = ComCls.cConst.PE_WEBSQL_MODE.R;
						}
						else if (oQueryString[ComCls.cConst.PC_WEBSQL_MODE] == ComCls.cConst.PC_WEBSQL_MODE_CUD)
						{
							eMode = ComCls.cConst.PE_WEBSQL_MODE.CUD;
						}
						else if (oQueryString[ComCls.cConst.PC_WEBSQL_MODE] == ComCls.cConst.PC_WEBSQL_MODE_TCUD)
						{
							eMode = ComCls.cConst.PE_WEBSQL_MODE.TCUD;
						}

						if (eMode != ComCls.cConst.PE_WEBSQL_MODE.EMPTY)
						{
							//---------------------------------------------------------------------------------------------------
							//데이터셋 반환 타입(PARSE/XML) 확인 : Type
							//---------------------------------------------------------------------------------------------------
							if (oQueryString.AllKeys[1] == ComCls.cConst.PC_WEBSQL_TYPE)
							{
								if (oQueryString[ComCls.cConst.PC_WEBSQL_TYPE] == ComCls.cConst.PC_WEBSQL_TYPE_PARSE)
								{
									eType = ComCls.cConst.PE_WEBSQL_TYPE.PARSE;
								}
								else if (oQueryString[ComCls.cConst.PC_WEBSQL_TYPE] == ComCls.cConst.PC_WEBSQL_TYPE_XML)
								{
									eType = ComCls.cConst.PE_WEBSQL_TYPE.XML;
								}

								if (eType != ComCls.cConst.PE_WEBSQL_TYPE.EMPTY)
								{
									//---------------------------------------------------------------------------------------------------
									//Sql 유형(TEXT/SP) 확인 : Style
									//---------------------------------------------------------------------------------------------------
									if (oQueryString.AllKeys[2] == ComCls.cConst.PC_WEBSQL_STYLE)
									{
										if (oQueryString[ComCls.cConst.PC_WEBSQL_STYLE] == ComCls.cConst.PC_WEBSQL_STYLE_TEXT)
										{
											eStyle = ComCls.cConst.PE_WEBSQL_STYLE.TEXT;
										}
										else if (oQueryString[ComCls.cConst.PC_WEBSQL_STYLE] == ComCls.cConst.PC_WEBSQL_STYLE_SP)
										{
											eStyle = ComCls.cConst.PE_WEBSQL_STYLE.SP;
										}

										switch (eStyle)
										{
											//---------------------------------------------------------------------------------------------------
											//데이터베이스 Embeded Sql 확인 : CmdTXT
											//---------------------------------------------------------------------------------------------------
											case ComCls.cConst.PE_WEBSQL_STYLE.TEXT:
												//if (oQueryString.AllKeys[3] == ComCls.cConst.PC_WEBSQL_CMD_TEXT)
												//{
												//    sCommand = oQueryString[ComCls.cConst.PC_WEBSQL_CMD_TEXT];

												//    if (sCommand != null && sCommand.Trim() != "")
												//    {
												//        bResult = true;
												//    }
												//}
												if (oQueryString.AllKeys[3] == ComCls.cConst.PC_WEBSQL_CMD_TEXT)
												{
													sCommand = oQueryString[ComCls.cConst.PC_WEBSQL_CMD_TEXT];

													if (sCommand != null && sCommand.Trim() != "")
													{
														if (eMode != ComCls.cConst.PE_WEBSQL_MODE.TCUD)
														{
															bResult = true;
														}
														else
														{
															if (sCommand == ComCls.cConst.PC_DB_TRANSACTION_CONNECT)
															{
																bResult = true;
															}
															else
															{
																if (oQueryString.AllKeys.Length == 5)
																{
																	sSID = oQueryString[ComCls.cConst.PC_WEBSQL_CMD_SID];

																	if (sSID != null && sSID.Trim() != "")
																	{
																		bResult = true;
																	}
																}
															}
														}
													}
												}

												break;
											//---------------------------------------------------------------------------------------------------
											//데이터베이스 Stord Procedure 확인 : CmdSP
											//---------------------------------------------------------------------------------------------------
											case ComCls.cConst.PE_WEBSQL_STYLE.SP:
												if (oQueryString.AllKeys[3] == ComCls.cConst.PC_WEBSQL_CMD_SP)
												{
													sCommand = oQueryString[ComCls.cConst.PC_WEBSQL_CMD_SP];

													if (sCommand != null && sCommand.Trim() != "")
													{
														if (eMode != ComCls.cConst.PE_WEBSQL_MODE.TCUD)
														{
															//---------------------------------------------------------------------------------------------------
															//Stord Procedure 인자 만들기
															//---------------------------------------------------------------------------------------------------
															saPaNames = new string[oQueryString.AllKeys.Length - 4];
															saPaValues = new string[oQueryString.AllKeys.Length - 4];

															bResult = true;

															for (int nIndex = 0; nIndex < saPaNames.Length; nIndex++)
															{
																if (oQueryString.AllKeys[nIndex + 4] != null)
																{
																	saPaNames[nIndex] = oQueryString.AllKeys[nIndex + 4];
																	saPaValues[nIndex] = oQueryString[oQueryString.AllKeys[nIndex + 4]];
																}
																else
																{
																	bResult = false;

																	break;
																}
															}
															//---------------------------------------------------------------------------------------------------
														}
														else
														{
															//---------------------------------------------------------------------------------------------------
															//트랜잭션 모드 명령어 & 입력/수정/삭제 작업 처리
															//---------------------------------------------------------------------------------------------------
															switch (sCommand)
															{
																//데이터베이스 연결
																case ComCls.cConst.PC_DB_TRANSACTION_CONNECT:
																	bResult = true;

																	break;
																//데이터베이스 트랜잭션 시작
																case ComCls.cConst.PC_DB_TRANSACTION_BEGINTRAN:
																case ComCls.cConst.PC_DB_TRANSACTION_COMMIT:
																case ComCls.cConst.PC_DB_TRANSACTION_ROLLBACK:
																case ComCls.cConst.PC_DB_TRANSACTION_DISCONNECT:
																	sSID = oQueryString[ComCls.cConst.PC_WEBSQL_CMD_SID];

																	if (sSID != null && sSID.Trim() != "")
																	{
																		bResult = true;
																	}

																	break;
																//데이터베이스 Sql 처리(입력/수정/삭제)
																default:
																	sSID = oQueryString[ComCls.cConst.PC_WEBSQL_CMD_SID];

																	if (sSID != null && sSID.Trim() != "")
																	{
																		//---------------------------------------------------------------------------------------------------
																		//Stord Procedure 인자 만들기
																		//---------------------------------------------------------------------------------------------------
																		saPaNames = new string[oQueryString.AllKeys.Length - 4 - 1];
																		saPaValues = new string[oQueryString.AllKeys.Length - 4 - 1];

																		bResult = true;

																		for (int nIndex = 0; nIndex < saPaNames.Length; nIndex++)
																		{
																			if (oQueryString.AllKeys[nIndex + 4] != null)
																			{
																				saPaNames[nIndex] = oQueryString.AllKeys[nIndex + 4];
																				saPaValues[nIndex] = oQueryString[oQueryString.AllKeys[nIndex + 4]];
																			}
																			else
																			{
																				bResult = false;

																				break;
																			}
																		}
																		//---------------------------------------------------------------------------------------------------
																	}

																	break;
															}
														}
													}
												}

												break;
										}
									}//Sql 실행 방식(TEXT/SP) 확인 : Style
								}
							}//데이터셋 반환 타입(PARSE/XML) 확인 : Type
						}
					}//Sql 실행 모드(CRUD) 확인 : Mode
				}//인자 개수 확인
			}
			catch (Exception ex)
			{
				bResult = false;

				throw ex;
			}

			return bResult;
		}
		#endregion

		//▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
	}// End class cFunction
}// End namespace ComCls
